Merge "Block background dream launch during widget launch and occlusion." into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index c768121..df4a3e5 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -100,6 +100,7 @@
"framework-jobscheduler-job.flags-aconfig-java",
"framework_graphics_flags_java_lib",
"hwui_flags_java_lib",
+ "interaction_jank_monitor_flags_lib",
"libcore_exported_aconfig_flags_lib",
"libgui_flags_java_lib",
"power_flags_lib",
@@ -1428,6 +1429,18 @@
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+java_aconfig_library {
+ name: "android.app.appfunctions.exported-flags-aconfig-java",
+ aconfig_declarations: "android.app.appfunctions.flags-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+ mode: "exported",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.permission",
+ ],
+ min_sdk_version: "30",
+}
+
// Adaptive Auth
aconfig_declarations {
name: "android.adaptiveauth.flags-aconfig",
@@ -1578,3 +1591,17 @@
aconfig_declarations: "dropbox_flags",
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+
+// Zero Jank
+aconfig_declarations {
+ name: "interaction_jank_monitor_flags",
+ package: "com.android.internal.jank",
+ container: "system",
+ srcs: ["core/java/com/android/internal/jank/flags.aconfig"],
+}
+
+java_aconfig_library {
+ name: "interaction_jank_monitor_flags_lib",
+ aconfig_declarations: "interaction_jank_monitor_flags",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
diff --git a/Ravenwood.bp b/Ravenwood.bp
index 5f32ba0..ec58210 100644
--- a/Ravenwood.bp
+++ b/Ravenwood.bp
@@ -50,7 +50,7 @@
framework_minus_apex_cmd = "$(location hoststubgen) " +
"@$(location :ravenwood-standard-options) " +
"--debug-log $(location hoststubgen_framework-minus-apex.log) " +
- "--out-impl-jar $(location ravenwood.jar) " +
+ "--out-jar $(location ravenwood.jar) " +
"--in-jar $(location :framework-minus-apex-for-hoststubgen) " +
"--policy-override-file $(location :ravenwood-framework-policies) " +
"--annotation-allowed-classes-file $(location :ravenwood-annotation-allowed-classes) "
@@ -183,7 +183,7 @@
"--stats-file $(location hoststubgen_services.core_stats.csv) " +
"--supported-api-list-file $(location hoststubgen_services.core_apis.csv) " +
- "--out-impl-jar $(location ravenwood.jar) " +
+ "--out-jar $(location ravenwood.jar) " +
"--gen-keep-all-file $(location hoststubgen_services.core_keep_all.txt) " +
"--gen-input-dump-file $(location hoststubgen_services.core_dump.txt) " +
diff --git a/apct-tests/perftests/core/AndroidTest.xml b/apct-tests/perftests/core/AndroidTest.xml
index 86f41e1..c2d5470 100644
--- a/apct-tests/perftests/core/AndroidTest.xml
+++ b/apct-tests/perftests/core/AndroidTest.xml
@@ -17,6 +17,17 @@
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-metric-instrumentation" />
+ // Deal with Play Protect blocking apk installations.
+ // The first setting disables the verification, the second one lowers the timeout from
+ // 1hr to 10s, the third one resets the value after the test is complete, and the final
+ // setting skips the device reboot after modifying the settings.
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <option name="set-global-setting" key="verifier_verify_adb_installs" value="0" />
+ <option name="set-global-setting" key="verifier_engprod" value="1" />
+ <option name="restore-settings" value="true" />
+ <option name="force-skip-system-props" value="true" />
+ </target_preparer>
+
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="push-file" key="trace_config_detailed.textproto" value="/data/misc/perfetto-traces/trace_config.textproto" />
diff --git a/apct-tests/perftests/core/src/android/app/OverlayManagerPerfTest.java b/apct-tests/perftests/core/src/android/app/OverlayManagerPerfTest.java
index fcb13a8..a12121f 100644
--- a/apct-tests/perftests/core/src/android/app/OverlayManagerPerfTest.java
+++ b/apct-tests/perftests/core/src/android/app/OverlayManagerPerfTest.java
@@ -37,9 +37,13 @@
import org.junit.Test;
import java.util.ArrayList;
-import java.util.concurrent.Executor;
-import java.util.concurrent.FutureTask;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Stream;
/**
* Benchmarks for {@link android.content.om.OverlayManager}.
@@ -49,7 +53,6 @@
private static final int OVERLAY_PKG_COUNT = 10;
private static Context sContext;
private static OverlayManager sOverlayManager;
- private static Executor sExecutor;
private static ArrayList<TestPackageInstaller.InstalledPackage> sSmallOverlays =
new ArrayList<>();
private static ArrayList<TestPackageInstaller.InstalledPackage> sLargeOverlays =
@@ -58,18 +61,45 @@
@Rule
public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+ // Uncheck the checked exceptions in a callable for convenient stream usage.
+ // Any exception will fail the test anyway.
+ private static <T> T uncheck(Callable<T> c) {
+ try {
+ return c.call();
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
@BeforeClass
public static void classSetUp() throws Exception {
sContext = InstrumentationRegistry.getTargetContext();
sOverlayManager = new OverlayManager(sContext);
- sExecutor = (command) -> new Thread(command).start();
- // Install all of the test overlays.
- TestPackageInstaller installer = new TestPackageInstaller(sContext);
+ // Install all of the test overlays. Play Protect likes to block these for 10 sec each
+ // so let's install them in parallel to speed up the wait.
+ final var installer = new TestPackageInstaller(sContext);
+ final var es = Executors.newFixedThreadPool(2 * OVERLAY_PKG_COUNT);
+ final var smallFutures = new ArrayList<Future<TestPackageInstaller.InstalledPackage>>(
+ OVERLAY_PKG_COUNT);
+ final var largeFutures = new ArrayList<Future<TestPackageInstaller.InstalledPackage>>(
+ OVERLAY_PKG_COUNT);
for (int i = 0; i < OVERLAY_PKG_COUNT; i++) {
- sSmallOverlays.add(installer.installPackage("Overlay" + i +".apk"));
- sLargeOverlays.add(installer.installPackage("LargeOverlay" + i +".apk"));
+ final var index = i;
+ smallFutures.add(es.submit(() -> installer.installPackage("Overlay" + index + ".apk")));
+ largeFutures.add(
+ es.submit(() -> installer.installPackage("LargeOverlay" + index + ".apk")));
}
+ es.shutdown();
+ assertTrue(es.awaitTermination(15 * 2 * OVERLAY_PKG_COUNT, TimeUnit.SECONDS));
+ sSmallOverlays.addAll(smallFutures.stream().map(f -> uncheck(f::get)).sorted(
+ Comparator.comparing(
+ TestPackageInstaller.InstalledPackage::getPackageName)).toList());
+ sLargeOverlays.addAll(largeFutures.stream().map(f -> uncheck(f::get)).sorted(
+ Comparator.comparing(
+ TestPackageInstaller.InstalledPackage::getPackageName)).toList());
}
@AfterClass
@@ -77,7 +107,6 @@
for (TestPackageInstaller.InstalledPackage overlay : sSmallOverlays) {
overlay.uninstall();
}
-
for (TestPackageInstaller.InstalledPackage overlay : sLargeOverlays) {
overlay.uninstall();
}
@@ -86,37 +115,39 @@
@After
public void tearDown() throws Exception {
// Disable all test overlays after each test.
- for (TestPackageInstaller.InstalledPackage overlay : sSmallOverlays) {
- assertSetEnabled(sContext, overlay.getPackageName(), false);
- }
-
- for (TestPackageInstaller.InstalledPackage overlay : sLargeOverlays) {
- assertSetEnabled(sContext, overlay.getPackageName(), false);
- }
+ assertSetEnabled(false, sContext,
+ Stream.concat(sSmallOverlays.stream(), sLargeOverlays.stream()).map(
+ p -> p.getPackageName()));
}
/**
- * Enables the overlay and waits for the APK path change sto be propagated to the context
+ * Enables the overlay and waits for the APK path changes to be propagated to the context
* AssetManager.
*/
- private void assertSetEnabled(Context context, String overlayPackage, boolean eanabled)
- throws Exception {
- sOverlayManager.setEnabled(overlayPackage, true, UserHandle.SYSTEM);
+ private void assertSetEnabled(boolean enabled, Context context, Stream<String> packagesStream) {
+ final var overlayPackages = packagesStream.toList();
+ overlayPackages.forEach(
+ name -> sOverlayManager.setEnabled(name, enabled, UserHandle.SYSTEM));
// Wait for the overlay changes to propagate
- FutureTask<Boolean> task = new FutureTask<>(() -> {
- while (true) {
- for (String path : context.getAssets().getApkPaths()) {
- if (eanabled == path.contains(overlayPackage)) {
- return true;
- }
- }
+ final var endTime = System.nanoTime() + TimeUnit.SECONDS.toNanos(20);
+ final var expectedPackagesFound = enabled ? overlayPackages.size() : 0;
+ boolean assetsUpdated = false;
+ do {
+ final var packagesFound = Arrays.stream(context.getAssets().getApkPaths()).filter(
+ assetPath -> overlayPackages.stream().anyMatch(assetPath::contains)).count();
+ if (packagesFound == expectedPackagesFound) {
+ assetsUpdated = true;
+ break;
}
- });
+ Thread.yield();
+ } while (System.nanoTime() < endTime);
+ assertTrue("Failed to set state to " + enabled + " for overlays " + overlayPackages,
+ assetsUpdated);
+ }
- sExecutor.execute(task);
- assertTrue("Failed to load overlay " + overlayPackage,
- task.get(20, TimeUnit.SECONDS));
+ private void assertSetEnabled(boolean enabled, Context context, String overlayPackage) {
+ assertSetEnabled(enabled, context, Stream.of(overlayPackage));
}
@Test
@@ -124,11 +155,11 @@
String packageName = sSmallOverlays.get(0).getPackageName();
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
- assertSetEnabled(sContext, packageName, true);
+ assertSetEnabled(true, sContext, packageName);
// Disable the overlay for the next iteration of the test
state.pauseTiming();
- assertSetEnabled(sContext, packageName, false);
+ assertSetEnabled(false, sContext, packageName);
state.resumeTiming();
}
}
@@ -138,11 +169,11 @@
String packageName = sSmallOverlays.get(0).getPackageName();
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
- assertSetEnabled(sContext, packageName, true);
+ assertSetEnabled(true, sContext, packageName);
// Disable the overlay and remove the idmap for the next iteration of the test
state.pauseTiming();
- assertSetEnabled(sContext, packageName, false);
+ assertSetEnabled(false, sContext, packageName);
sOverlayManager.invalidateCachesForOverlay(packageName, UserHandle.SYSTEM);
state.resumeTiming();
}
@@ -153,11 +184,11 @@
String packageName = sLargeOverlays.get(0).getPackageName();
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
- assertSetEnabled(sContext, packageName, true);
+ assertSetEnabled(true, sContext, packageName);
// Disable the overlay and remove the idmap for the next iteration of the test
state.pauseTiming();
- assertSetEnabled(sContext, packageName, false);
+ assertSetEnabled(false, sContext, packageName);
sOverlayManager.invalidateCachesForOverlay(packageName, UserHandle.SYSTEM);
state.resumeTiming();
}
@@ -169,30 +200,28 @@
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
state.pauseTiming();
- assertSetEnabled(sContext, packageName, true);
+ assertSetEnabled(true, sContext, packageName);
state.resumeTiming();
- assertSetEnabled(sContext, packageName, false);
+ assertSetEnabled(false, sContext, packageName);
}
}
@Test
public void getStringOneSmallOverlay() throws Exception {
String packageName = sSmallOverlays.get(0).getPackageName();
- assertSetEnabled(sContext, packageName, true);
+ assertSetEnabled(true, sContext, packageName);
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
sContext.getString(R.string.short_text);
}
-
- assertSetEnabled(sContext, packageName, false);
}
@Test
public void getStringOneLargeOverlay() throws Exception {
String packageName = sLargeOverlays.get(0).getPackageName();
- assertSetEnabled(sContext, packageName, true);
+ assertSetEnabled(true, sContext, packageName);
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
@@ -200,16 +229,12 @@
sContext.getString(resId);
}
}
-
- assertSetEnabled(sContext, packageName, false);
}
@Test
public void getStringTenOverlays() throws Exception {
- // Enable all test overlays
- for (TestPackageInstaller.InstalledPackage overlay : sSmallOverlays) {
- assertSetEnabled(sContext, overlay.getPackageName(), true);
- }
+ // Enable all small test overlays
+ assertSetEnabled(true, sContext, sSmallOverlays.stream().map(p -> p.getPackageName()));
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
@@ -219,10 +244,8 @@
@Test
public void getStringLargeTenOverlays() throws Exception {
- // Enable all test overlays
- for (TestPackageInstaller.InstalledPackage overlay : sLargeOverlays) {
- assertSetEnabled(sContext, overlay.getPackageName(), true);
- }
+ // Enable all large test overlays
+ assertSetEnabled(true, sContext, sLargeOverlays.stream().map(p -> p.getPackageName()));
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java
index f20b170..3577fcd 100644
--- a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java
+++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java
@@ -194,7 +194,7 @@
/**
* Simple benchmark for the amount of time to send a given number of messages
*/
- @Test
+ // @Test Temporarily disabled
@Parameters(method = "getParams")
public void time(Config config) throws Exception {
reset();
diff --git a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java
index af3c405..ac57100 100644
--- a/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java
+++ b/apct-tests/perftests/core/src/android/conscrypt/conscrypt/ServerSocketPerfTest.java
@@ -198,7 +198,7 @@
executor.awaitTermination(5, TimeUnit.SECONDS);
}
- @Test
+ // @Test Temporarily disabled
@Parameters(method = "getParams")
public void throughput(Config config) throws Exception {
setup(config);
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/ByteBufferPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/ByteBufferPerfTest.java
index 4cf46e5..f01ac02 100644
--- a/apct-tests/perftests/core/src/android/libcore/regression/ByteBufferPerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/regression/ByteBufferPerfTest.java
@@ -565,7 +565,6 @@
}
@Test
- @Parameters(method = "getData")
public void time_new_byteArray() throws Exception {
final BenchmarkState state = mBenchmarkRule.getState();
while (state.keepRunning()) {
@@ -574,7 +573,6 @@
}
@Test
- @Parameters(method = "getData")
public void time_ByteBuffer_allocate() throws Exception {
final BenchmarkState state = mBenchmarkRule.getState();
while (state.keepRunning()) {
diff --git a/apex/jobscheduler/framework/aconfig/job.aconfig b/apex/jobscheduler/framework/aconfig/job.aconfig
index 80db264..5f55075 100644
--- a/apex/jobscheduler/framework/aconfig/job.aconfig
+++ b/apex/jobscheduler/framework/aconfig/job.aconfig
@@ -23,3 +23,10 @@
description: "Introduce a new RUN_BACKUP_JOBS permission and exemption logic allowing for longer running jobs for apps whose primary purpose is to backup or sync content."
bug: "318731461"
}
+
+flag {
+ name: "cleanup_empty_jobs"
+ namespace: "backstage_power"
+ description: "Enables automatic cancellation of jobs due to leaked JobParameters, reducing unnecessary battery drain and improving system efficiency. This includes logging and traces for better issue diagnosis."
+ bug: "349688611"
+}
diff --git a/apex/jobscheduler/framework/java/android/app/job/IJobCallback.aidl b/apex/jobscheduler/framework/java/android/app/job/IJobCallback.aidl
index 96494ec..11d17ca 100644
--- a/apex/jobscheduler/framework/java/android/app/job/IJobCallback.aidl
+++ b/apex/jobscheduler/framework/java/android/app/job/IJobCallback.aidl
@@ -85,6 +85,14 @@
*/
@UnsupportedAppUsage
void jobFinished(int jobId, boolean reschedule);
+
+ /*
+ * Inform JobScheduler to force finish this job because the client has lost
+ * the job handle. jobFinished can no longer be called from the client.
+ * @param jobId Unique integer used to identify this job
+ */
+ void forceJobFinished(int jobId);
+
/*
* Inform JobScheduler of a change in the estimated transfer payload.
*
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
index e833bb9..52a761f 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
@@ -34,15 +34,21 @@
import android.os.Parcelable;
import android.os.PersistableBundle;
import android.os.RemoteException;
+import android.system.SystemCleaner;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.Cleaner;
/**
* Contains the parameters used to configure/identify your job. You do not create this object
* yourself, instead it is handed in to your application by the System.
*/
public class JobParameters implements Parcelable {
+ private static final String TAG = "JobParameters";
/** @hide */
public static final int INTERNAL_STOP_REASON_UNKNOWN = -1;
@@ -306,6 +312,10 @@
private int mStopReason = STOP_REASON_UNDEFINED;
private int mInternalStopReason = INTERNAL_STOP_REASON_UNKNOWN;
private String debugStopReason; // Human readable stop reason for debugging.
+ @Nullable
+ private JobCleanupCallback mJobCleanupCallback;
+ @Nullable
+ private Cleaner.Cleanable mCleanable;
/** @hide */
public JobParameters(IBinder callback, String namespace, int jobId, PersistableBundle extras,
@@ -326,6 +336,8 @@
this.mTriggeredContentAuthorities = triggeredContentAuthorities;
this.mNetwork = network;
this.mJobNamespace = namespace;
+ this.mJobCleanupCallback = null;
+ this.mCleanable = null;
}
/**
@@ -597,6 +609,8 @@
mStopReason = in.readInt();
mInternalStopReason = in.readInt();
debugStopReason = in.readString();
+ mJobCleanupCallback = null;
+ mCleanable = null;
}
/** @hide */
@@ -612,6 +626,54 @@
this.debugStopReason = debugStopReason;
}
+ /** @hide */
+ public void initCleaner(JobCleanupCallback jobCleanupCallback) {
+ mJobCleanupCallback = jobCleanupCallback;
+ mCleanable = SystemCleaner.cleaner().register(this, mJobCleanupCallback);
+ }
+
+ /**
+ * Lazy initialize the cleaner and enable it
+ *
+ * @hide
+ */
+ public void enableCleaner() {
+ if (mJobCleanupCallback == null) {
+ initCleaner(new JobCleanupCallback(IJobCallback.Stub.asInterface(callback), jobId));
+ }
+ mJobCleanupCallback.enableCleaner();
+ }
+
+ /**
+ * Disable the cleaner from running and unregister it
+ *
+ * @hide
+ */
+ public void disableCleaner() {
+ if (mJobCleanupCallback != null) {
+ mJobCleanupCallback.disableCleaner();
+ if (mCleanable != null) {
+ mCleanable.clean();
+ mCleanable = null;
+ }
+ mJobCleanupCallback = null;
+ }
+ }
+
+ /** @hide */
+ @VisibleForTesting
+ @Nullable
+ public Cleaner.Cleanable getCleanable() {
+ return mCleanable;
+ }
+
+ /** @hide */
+ @VisibleForTesting
+ @Nullable
+ public JobCleanupCallback getJobCleanupCallback() {
+ return mJobCleanupCallback;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -647,6 +709,67 @@
dest.writeString(debugStopReason);
}
+ /**
+ * JobCleanupCallback is used track JobParameters leak. If the job is started
+ * and jobFinish is not called at the time of garbage collection of JobParameters
+ * instance, it is considered a job leak. Force finish the job.
+ *
+ * @hide
+ */
+ public static class JobCleanupCallback implements Runnable {
+ private final IJobCallback mCallback;
+ private final int mJobId;
+ private boolean mIsCleanerEnabled;
+
+ public JobCleanupCallback(
+ IJobCallback callback,
+ int jobId) {
+ mCallback = callback;
+ mJobId = jobId;
+ mIsCleanerEnabled = false;
+ }
+
+ /**
+ * Check if the cleaner is enabled
+ *
+ * @hide
+ */
+ public boolean isCleanerEnabled() {
+ return mIsCleanerEnabled;
+ }
+
+ /**
+ * Enable the cleaner to detect JobParameter leak
+ *
+ * @hide
+ */
+ public void enableCleaner() {
+ mIsCleanerEnabled = true;
+ }
+
+ /**
+ * Disable the cleaner from running.
+ *
+ * @hide
+ */
+ public void disableCleaner() {
+ mIsCleanerEnabled = false;
+ }
+
+ /** @hide */
+ @Override
+ public void run() {
+ if (!isCleanerEnabled()) {
+ return;
+ }
+ try {
+ mCallback.forceJobFinished(mJobId);
+ } catch (Exception e) {
+ Log.wtf(TAG, "Could not destroy running job", e);
+ }
+ }
+ }
+
public static final @android.annotation.NonNull Creator<JobParameters> CREATOR = new Creator<JobParameters>() {
@Override
public JobParameters createFromParcel(Parcel in) {
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java b/apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java
index 79d87ed..5f80c52 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobServiceEngine.java
@@ -165,7 +165,13 @@
case MSG_EXECUTE_JOB: {
final JobParameters params = (JobParameters) msg.obj;
try {
+ if (Flags.cleanupEmptyJobs()) {
+ params.enableCleaner();
+ }
boolean workOngoing = JobServiceEngine.this.onStartJob(params);
+ if (Flags.cleanupEmptyJobs() && !workOngoing) {
+ params.disableCleaner();
+ }
ackStartMessage(params, workOngoing);
} catch (Exception e) {
Log.e(TAG, "Error while executing job: " + params.getJobId());
@@ -190,6 +196,9 @@
IJobCallback callback = params.getCallback();
if (callback != null) {
try {
+ if (Flags.cleanupEmptyJobs()) {
+ params.disableCleaner();
+ }
callback.jobFinished(params.getJobId(), needsReschedule);
} catch (RemoteException e) {
Log.e(TAG, "Error reporting job finish to system: binder has gone" +
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 3d25ed5..97c6e25 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -5808,9 +5808,10 @@
static void dumpHelp(PrintWriter pw) {
pw.println("Job Scheduler (jobscheduler) dump options:");
- pw.println(" [-h] [package] ...");
+ pw.println(" [-h] [package] [--proto] ...");
pw.println(" -h: print this help");
pw.println(" [package] is an optional package name to limit the output to.");
+ pw.println(" --proto: output dump in protocol buffer format.");
}
/** Sort jobs by caller UID, then by Job ID. */
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index be8e304..ee246d8 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -129,6 +129,8 @@
private static final String[] VERB_STRINGS = {
"VERB_BINDING", "VERB_STARTING", "VERB_EXECUTING", "VERB_STOPPING", "VERB_FINISHED"
};
+ private static final String TRACE_JOB_FORCE_FINISHED_PREFIX = "forceJobFinished:";
+ private static final String TRACE_JOB_FORCE_FINISHED_DELIMITER = "#";
// States that a job occupies while interacting with the client.
static final int VERB_BINDING = 0;
@@ -292,6 +294,11 @@
}
@Override
+ public void forceJobFinished(int jobId) {
+ doForceJobFinished(this, jobId);
+ }
+
+ @Override
public void updateEstimatedNetworkBytes(int jobId, JobWorkItem item,
long downloadBytes, long uploadBytes) {
doUpdateEstimatedNetworkBytes(this, jobId, item, downloadBytes, uploadBytes);
@@ -762,6 +769,35 @@
}
}
+ /**
+ * This method just adds traces to evaluate jobs that leak jobparameters at the client.
+ * It does not stop the job.
+ */
+ void doForceJobFinished(JobCallback cb, int jobId) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ final JobStatus executing;
+ synchronized (mLock) {
+ // not the current job, presumably it has finished in some way already
+ if (!verifyCallerLocked(cb)) {
+ return;
+ }
+
+ executing = getRunningJobLocked();
+ }
+ if (executing != null && jobId == executing.getJobId()) {
+ final StringBuilder stateSuffix = new StringBuilder();
+ stateSuffix.append(TRACE_JOB_FORCE_FINISHED_PREFIX);
+ stateSuffix.append(executing.getBatteryName());
+ stateSuffix.append(TRACE_JOB_FORCE_FINISHED_DELIMITER);
+ stateSuffix.append(executing.getJobId());
+ Trace.instant(Trace.TRACE_TAG_POWER, stateSuffix.toString());
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
private void doAcknowledgeGetTransferredDownloadBytesMessage(JobCallback cb, int jobId,
int workId, @BytesLong long transferredBytes) {
// TODO(255393346): Make sure apps call this appropriately and monitor for abuse
diff --git a/api/api.go b/api/api.go
index 5b7f534..e9f1fee 100644
--- a/api/api.go
+++ b/api/api.go
@@ -15,7 +15,7 @@
package api
import (
- "sort"
+ "slices"
"github.com/google/blueprint/proptools"
@@ -75,31 +75,25 @@
var PrepareForCombinedApisTest = android.FixtureRegisterWithContext(registerBuildComponents)
-func (a *CombinedApis) bootclasspath(ctx android.ConfigAndErrorContext) []string {
- return a.properties.Bootclasspath.GetOrDefault(a.ConfigurableEvaluator(ctx), nil)
-}
-
-func (a *CombinedApis) systemServerClasspath(ctx android.ConfigAndErrorContext) []string {
- return a.properties.System_server_classpath.GetOrDefault(a.ConfigurableEvaluator(ctx), nil)
-}
-
func (a *CombinedApis) apiFingerprintStubDeps(ctx android.BottomUpMutatorContext) []string {
- ret := []string{}
+ bootClasspath := a.properties.Bootclasspath.GetOrDefault(ctx, nil)
+ systemServerClasspath := a.properties.System_server_classpath.GetOrDefault(ctx, nil)
+ var ret []string
ret = append(
ret,
- transformArray(a.bootclasspath(ctx), "", ".stubs")...,
+ transformArray(bootClasspath, "", ".stubs")...,
)
ret = append(
ret,
- transformArray(a.bootclasspath(ctx), "", ".stubs.system")...,
+ transformArray(bootClasspath, "", ".stubs.system")...,
)
ret = append(
ret,
- transformArray(a.bootclasspath(ctx), "", ".stubs.module_lib")...,
+ transformArray(bootClasspath, "", ".stubs.module_lib")...,
)
ret = append(
ret,
- transformArray(a.systemServerClasspath(ctx), "", ".stubs.system_server")...,
+ transformArray(systemServerClasspath, "", ".stubs.system_server")...,
)
return ret
}
@@ -129,7 +123,7 @@
Cmd *string
Dists []android.Dist
Out []string
- Srcs []string
+ Srcs proptools.Configurable[[]string]
Tools []string
Visibility []string
}
@@ -137,7 +131,7 @@
type libraryProps struct {
Name *string
Sdk_version *string
- Static_libs []string
+ Static_libs proptools.Configurable[[]string]
Visibility []string
Defaults []string
Is_stubs_module *bool
@@ -145,7 +139,7 @@
type fgProps struct {
Name *string
- Srcs []string
+ Srcs proptools.Configurable[[]string]
Visibility []string
}
@@ -166,7 +160,7 @@
// The module for the non-updatable / non-module part of the api.
BaseTxt string
// The list of modules that are relevant for this merged txt.
- Modules []string
+ Modules proptools.Configurable[[]string]
// The output tag for each module to use.e.g. {.public.api.txt} for current.txt
ModuleTag string
// public, system, module-lib or system-server
@@ -190,7 +184,8 @@
props.Tools = []string{"metalava"}
props.Out = []string{filename}
props.Cmd = proptools.StringPtr(metalavaCmd + "$(in) --out $(out)")
- props.Srcs = append([]string{txt.BaseTxt}, createSrcs(txt.Modules, txt.ModuleTag)...)
+ props.Srcs = proptools.NewSimpleConfigurable([]string{txt.BaseTxt})
+ props.Srcs.Append(createSrcs(txt.Modules, txt.ModuleTag))
if doDist {
props.Dists = []android.Dist{
{
@@ -209,11 +204,11 @@
ctx.CreateModule(genrule.GenRuleFactory, &props)
}
-func createMergedAnnotationsFilegroups(ctx android.LoadHookContext, modules, system_server_modules []string) {
+func createMergedAnnotationsFilegroups(ctx android.LoadHookContext, modules, system_server_modules proptools.Configurable[[]string]) {
for _, i := range []struct {
name string
tag string
- modules []string
+ modules proptools.Configurable[[]string]
}{
{
name: "all-modules-public-annotations",
@@ -240,33 +235,39 @@
}
}
-func createMergedPublicStubs(ctx android.LoadHookContext, modules []string) {
+func createMergedPublicStubs(ctx android.LoadHookContext, modules proptools.Configurable[[]string]) {
+ modules = modules.Clone()
+ transformConfigurableArray(modules, "", ".stubs")
props := libraryProps{}
props.Name = proptools.StringPtr("all-modules-public-stubs")
- props.Static_libs = transformArray(modules, "", ".stubs")
+ props.Static_libs = modules
props.Sdk_version = proptools.StringPtr("module_current")
props.Visibility = []string{"//frameworks/base"}
props.Is_stubs_module = proptools.BoolPtr(true)
ctx.CreateModule(java.LibraryFactory, &props)
}
-func createMergedPublicExportableStubs(ctx android.LoadHookContext, modules []string) {
+func createMergedPublicExportableStubs(ctx android.LoadHookContext, modules proptools.Configurable[[]string]) {
+ modules = modules.Clone()
+ transformConfigurableArray(modules, "", ".stubs.exportable")
props := libraryProps{}
props.Name = proptools.StringPtr("all-modules-public-stubs-exportable")
- props.Static_libs = transformArray(modules, "", ".stubs.exportable")
+ props.Static_libs = modules
props.Sdk_version = proptools.StringPtr("module_current")
props.Visibility = []string{"//frameworks/base"}
props.Is_stubs_module = proptools.BoolPtr(true)
ctx.CreateModule(java.LibraryFactory, &props)
}
-func createMergedSystemStubs(ctx android.LoadHookContext, modules []string) {
+func createMergedSystemStubs(ctx android.LoadHookContext, modules proptools.Configurable[[]string]) {
// First create the all-updatable-modules-system-stubs
{
- updatable_modules := removeAll(modules, non_updatable_modules)
+ updatable_modules := modules.Clone()
+ removeAll(updatable_modules, non_updatable_modules)
+ transformConfigurableArray(updatable_modules, "", ".stubs.system")
props := libraryProps{}
props.Name = proptools.StringPtr("all-updatable-modules-system-stubs")
- props.Static_libs = transformArray(updatable_modules, "", ".stubs.system")
+ props.Static_libs = updatable_modules
props.Sdk_version = proptools.StringPtr("module_current")
props.Visibility = []string{"//frameworks/base"}
props.Is_stubs_module = proptools.BoolPtr(true)
@@ -275,10 +276,11 @@
// Now merge all-updatable-modules-system-stubs and stubs from non-updatable modules
// into all-modules-system-stubs.
{
+ static_libs := transformArray(non_updatable_modules, "", ".stubs.system")
+ static_libs = append(static_libs, "all-updatable-modules-system-stubs")
props := libraryProps{}
props.Name = proptools.StringPtr("all-modules-system-stubs")
- props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.system")
- props.Static_libs = append(props.Static_libs, "all-updatable-modules-system-stubs")
+ props.Static_libs = proptools.NewSimpleConfigurable(static_libs)
props.Sdk_version = proptools.StringPtr("module_current")
props.Visibility = []string{"//frameworks/base"}
props.Is_stubs_module = proptools.BoolPtr(true)
@@ -286,13 +288,15 @@
}
}
-func createMergedSystemExportableStubs(ctx android.LoadHookContext, modules []string) {
+func createMergedSystemExportableStubs(ctx android.LoadHookContext, modules proptools.Configurable[[]string]) {
// First create the all-updatable-modules-system-stubs
{
- updatable_modules := removeAll(modules, non_updatable_modules)
+ updatable_modules := modules.Clone()
+ removeAll(updatable_modules, non_updatable_modules)
+ transformConfigurableArray(updatable_modules, "", ".stubs.exportable.system")
props := libraryProps{}
props.Name = proptools.StringPtr("all-updatable-modules-system-stubs-exportable")
- props.Static_libs = transformArray(updatable_modules, "", ".stubs.exportable.system")
+ props.Static_libs = updatable_modules
props.Sdk_version = proptools.StringPtr("module_current")
props.Visibility = []string{"//frameworks/base"}
props.Is_stubs_module = proptools.BoolPtr(true)
@@ -301,10 +305,11 @@
// Now merge all-updatable-modules-system-stubs and stubs from non-updatable modules
// into all-modules-system-stubs.
{
+ static_libs := transformArray(non_updatable_modules, "", ".stubs.exportable.system")
+ static_libs = append(static_libs, "all-updatable-modules-system-stubs-exportable")
props := libraryProps{}
props.Name = proptools.StringPtr("all-modules-system-stubs-exportable")
- props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.exportable.system")
- props.Static_libs = append(props.Static_libs, "all-updatable-modules-system-stubs-exportable")
+ props.Static_libs = proptools.NewSimpleConfigurable(static_libs)
props.Sdk_version = proptools.StringPtr("module_current")
props.Visibility = []string{"//frameworks/base"}
props.Is_stubs_module = proptools.BoolPtr(true)
@@ -315,7 +320,7 @@
func createMergedTestStubsForNonUpdatableModules(ctx android.LoadHookContext) {
props := libraryProps{}
props.Name = proptools.StringPtr("all-non-updatable-modules-test-stubs")
- props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.test")
+ props.Static_libs = proptools.NewSimpleConfigurable(transformArray(non_updatable_modules, "", ".stubs.test"))
props.Sdk_version = proptools.StringPtr("module_current")
props.Visibility = []string{"//frameworks/base"}
props.Is_stubs_module = proptools.BoolPtr(true)
@@ -325,25 +330,27 @@
func createMergedTestExportableStubsForNonUpdatableModules(ctx android.LoadHookContext) {
props := libraryProps{}
props.Name = proptools.StringPtr("all-non-updatable-modules-test-stubs-exportable")
- props.Static_libs = transformArray(non_updatable_modules, "", ".stubs.exportable.test")
+ props.Static_libs = proptools.NewSimpleConfigurable(transformArray(non_updatable_modules, "", ".stubs.exportable.test"))
props.Sdk_version = proptools.StringPtr("module_current")
props.Visibility = []string{"//frameworks/base"}
props.Is_stubs_module = proptools.BoolPtr(true)
ctx.CreateModule(java.LibraryFactory, &props)
}
-func createMergedFrameworkImpl(ctx android.LoadHookContext, modules []string) {
+func createMergedFrameworkImpl(ctx android.LoadHookContext, modules proptools.Configurable[[]string]) {
+ modules = modules.Clone()
// This module is for the "framework-all" module, which should not include the core libraries.
- modules = removeAll(modules, core_libraries_modules)
+ removeAll(modules, core_libraries_modules)
// Remove the modules that belong to non-updatable APEXes since those are allowed to compile
// against unstable APIs.
- modules = removeAll(modules, non_updatable_modules)
+ removeAll(modules, non_updatable_modules)
// First create updatable-framework-module-impl, which contains all updatable modules.
// This module compiles against module_lib SDK.
{
+ transformConfigurableArray(modules, "", ".impl")
props := libraryProps{}
props.Name = proptools.StringPtr("updatable-framework-module-impl")
- props.Static_libs = transformArray(modules, "", ".impl")
+ props.Static_libs = modules
props.Sdk_version = proptools.StringPtr("module_current")
props.Visibility = []string{"//frameworks/base"}
ctx.CreateModule(java.LibraryFactory, &props)
@@ -352,65 +359,74 @@
// Now create all-framework-module-impl, which contains updatable-framework-module-impl
// and all non-updatable modules. This module compiles against hidden APIs.
{
+ static_libs := transformArray(non_updatable_modules, "", ".impl")
+ static_libs = append(static_libs, "updatable-framework-module-impl")
props := libraryProps{}
props.Name = proptools.StringPtr("all-framework-module-impl")
- props.Static_libs = transformArray(non_updatable_modules, "", ".impl")
- props.Static_libs = append(props.Static_libs, "updatable-framework-module-impl")
+ props.Static_libs = proptools.NewSimpleConfigurable(static_libs)
props.Sdk_version = proptools.StringPtr("core_platform")
props.Visibility = []string{"//frameworks/base"}
ctx.CreateModule(java.LibraryFactory, &props)
}
}
-func createMergedFrameworkModuleLibExportableStubs(ctx android.LoadHookContext, modules []string) {
+func createMergedFrameworkModuleLibExportableStubs(ctx android.LoadHookContext, modules proptools.Configurable[[]string]) {
+ modules = modules.Clone()
// The user of this module compiles against the "core" SDK and against non-updatable modules,
// so remove to avoid dupes.
- modules = removeAll(modules, core_libraries_modules)
- modules = removeAll(modules, non_updatable_modules)
+ removeAll(modules, core_libraries_modules)
+ removeAll(modules, non_updatable_modules)
+ transformConfigurableArray(modules, "", ".stubs.exportable.module_lib")
props := libraryProps{}
props.Name = proptools.StringPtr("framework-updatable-stubs-module_libs_api-exportable")
- props.Static_libs = transformArray(modules, "", ".stubs.exportable.module_lib")
+ props.Static_libs = modules
props.Sdk_version = proptools.StringPtr("module_current")
props.Visibility = []string{"//frameworks/base"}
props.Is_stubs_module = proptools.BoolPtr(true)
ctx.CreateModule(java.LibraryFactory, &props)
}
-func createMergedFrameworkModuleLibStubs(ctx android.LoadHookContext, modules []string) {
+func createMergedFrameworkModuleLibStubs(ctx android.LoadHookContext, modules proptools.Configurable[[]string]) {
+ modules = modules.Clone()
// The user of this module compiles against the "core" SDK and against non-updatable modules,
// so remove to avoid dupes.
- modules = removeAll(modules, core_libraries_modules)
- modules = removeAll(modules, non_updatable_modules)
+ removeAll(modules, core_libraries_modules)
+ removeAll(modules, non_updatable_modules)
+ transformConfigurableArray(modules, "", ".stubs.module_lib")
props := libraryProps{}
props.Name = proptools.StringPtr("framework-updatable-stubs-module_libs_api")
- props.Static_libs = transformArray(modules, "", ".stubs.module_lib")
+ props.Static_libs = modules
props.Sdk_version = proptools.StringPtr("module_current")
props.Visibility = []string{"//frameworks/base"}
props.Is_stubs_module = proptools.BoolPtr(true)
ctx.CreateModule(java.LibraryFactory, &props)
}
-func createMergedFrameworkSystemServerExportableStubs(ctx android.LoadHookContext, bootclasspath, system_server_classpath []string) {
+func createMergedFrameworkSystemServerExportableStubs(ctx android.LoadHookContext, bootclasspath, system_server_classpath proptools.Configurable[[]string]) {
// The user of this module compiles against the "core" SDK and against non-updatable bootclasspathModules,
// so remove to avoid dupes.
- bootclasspathModules := removeAll(bootclasspath, core_libraries_modules)
- bootclasspathModules = removeAll(bootclasspath, non_updatable_modules)
- modules := append(
- // Include all the module-lib APIs from the bootclasspath libraries.
- transformArray(bootclasspathModules, "", ".stubs.exportable.module_lib"),
- // Then add all the system-server APIs from the service-* libraries.
- transformArray(system_server_classpath, "", ".stubs.exportable.system_server")...,
- )
+ bootclasspathModules := bootclasspath.Clone()
+ removeAll(bootclasspathModules, core_libraries_modules)
+ removeAll(bootclasspathModules, non_updatable_modules)
+ transformConfigurableArray(bootclasspathModules, "", ".stubs.exportable.module_lib")
+
+ system_server_classpath = system_server_classpath.Clone()
+ transformConfigurableArray(system_server_classpath, "", ".stubs.exportable.system_server")
+
+ // Include all the module-lib APIs from the bootclasspath libraries.
+ // Then add all the system-server APIs from the service-* libraries.
+ bootclasspathModules.Append(system_server_classpath)
+
props := libraryProps{}
props.Name = proptools.StringPtr("framework-updatable-stubs-system_server_api-exportable")
- props.Static_libs = modules
+ props.Static_libs = bootclasspathModules
props.Sdk_version = proptools.StringPtr("system_server_current")
props.Visibility = []string{"//frameworks/base"}
props.Is_stubs_module = proptools.BoolPtr(true)
ctx.CreateModule(java.LibraryFactory, &props)
}
-func createPublicStubsSourceFilegroup(ctx android.LoadHookContext, modules []string) {
+func createPublicStubsSourceFilegroup(ctx android.LoadHookContext, modules proptools.Configurable[[]string]) {
props := fgProps{}
props.Name = proptools.StringPtr("all-modules-public-stubs-source")
props.Srcs = createSrcs(modules, "{.public.stubs.source}")
@@ -418,7 +434,14 @@
ctx.CreateModule(android.FileGroupFactory, &props)
}
-func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_classpath []string, baseTxtModulePrefix, stubsTypeSuffix string, doDist bool) {
+func createMergedTxts(
+ ctx android.LoadHookContext,
+ bootclasspath proptools.Configurable[[]string],
+ system_server_classpath proptools.Configurable[[]string],
+ baseTxtModulePrefix string,
+ stubsTypeSuffix string,
+ doDist bool,
+) {
var textFiles []MergedTxtDefinition
tagSuffix := []string{".api.txt}", ".removed-api.txt}"}
@@ -463,11 +486,10 @@
}
func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) {
- bootclasspath := a.bootclasspath(ctx)
- system_server_classpath := a.systemServerClasspath(ctx)
+ bootclasspath := a.properties.Bootclasspath.Clone()
+ system_server_classpath := a.properties.System_server_classpath.Clone()
if ctx.Config().VendorConfig("ANDROID").Bool("include_nonpublic_framework_api") {
- bootclasspath = append(bootclasspath, a.properties.Conditional_bootclasspath...)
- sort.Strings(bootclasspath)
+ bootclasspath.AppendSimpleValue(a.properties.Conditional_bootclasspath)
}
createMergedTxts(ctx, bootclasspath, system_server_classpath, "non-updatable-", "-", false)
createMergedTxts(ctx, bootclasspath, system_server_classpath, "non-updatable-exportable-", "-exportable-", true)
@@ -500,8 +522,10 @@
// Various utility methods below.
// Creates an array of ":<m><tag>" for each m in <modules>.
-func createSrcs(modules []string, tag string) []string {
- return transformArray(modules, ":", tag)
+func createSrcs(modules proptools.Configurable[[]string], tag string) proptools.Configurable[[]string] {
+ result := modules.Clone()
+ transformConfigurableArray(result, ":", tag)
+ return result
}
// Creates an array of "<prefix><m><suffix>", for each m in <modules>.
@@ -513,11 +537,23 @@
return a
}
-func removeAll(s []string, vs []string) []string {
- for _, v := range vs {
- s = remove(s, v)
- }
- return s
+// Creates an array of "<prefix><m><suffix>", for each m in <modules>.
+func transformConfigurableArray(modules proptools.Configurable[[]string], prefix, suffix string) {
+ modules.AddPostProcessor(func(s []string) []string {
+ return transformArray(s, prefix, suffix)
+ })
+}
+
+func removeAll(s proptools.Configurable[[]string], vs []string) {
+ s.AddPostProcessor(func(s []string) []string {
+ a := make([]string, 0, len(s))
+ for _, module := range s {
+ if !slices.Contains(vs, module) {
+ a = append(a, module)
+ }
+ }
+ return a
+ })
}
func remove(s []string, v string) []string {
diff --git a/cmds/uinput/examples/test-touchpad.evemu b/cmds/uinput/examples/test-touchpad.evemu
new file mode 100644
index 0000000..34ee572
--- /dev/null
+++ b/cmds/uinput/examples/test-touchpad.evemu
@@ -0,0 +1,44 @@
+# EVEMU 1.2
+# This is an evemu "recording" of an Apple Magic Trackpad (1st generation), but
+# that doesn't actually make any movements. It just runs for a very long time,
+# to make Android think a touchpad is connected. This is useful for testing
+# things like the settings in System > Touchpad, which only appear when one is
+# connected.
+#
+# It can be played by piping it to the uinput command over ADB:
+# $ adb shell uinput - < test-touchpad.evemu
+N: Fake touchpad
+I: 0005 05ac 030e 0160
+P: 05 00 00 00 00 00 00 00
+B: 00 0b 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 01 00 00 00 00 00
+B: 01 20 e5 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 01 00 00 00 00 00 00 00 00
+B: 02 00 00 00 00 00 00 00 00
+B: 03 03 00 00 00 00 80 73 02
+B: 04 10 00 00 00 00 00 00 00
+B: 05 00 00 00 00 00 00 00 00
+B: 11 00 00 00 00 00 00 00 00
+B: 12 00 00 00 00 00 00 00 00
+A: 00 -2909 3167 4 0 46
+A: 01 -2456 2565 4 0 45
+A: 2f 0 15 0 0 0
+A: 30 0 1020 4 0 0
+A: 31 0 1020 4 0 0
+A: 34 -31 32 1 0 0
+A: 35 -2909 3167 4 0 46
+A: 36 -2456 2565 4 0 45
+A: 39 0 65535 0 0 0
+E: 0.000001 0004 0005 1234
+E: 0.000001 0000 0000 0000
+E: 1000000000.000000 0004 0005 1235
+E: 1000000000.000000 0000 0000 0000
diff --git a/core/api/current.txt b/core/api/current.txt
index ddfd364..5e8febe 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -145,12 +145,12 @@
field public static final String MANAGE_DEVICE_POLICY_AUDIO_OUTPUT = "android.permission.MANAGE_DEVICE_POLICY_AUDIO_OUTPUT";
field public static final String MANAGE_DEVICE_POLICY_AUTOFILL = "android.permission.MANAGE_DEVICE_POLICY_AUTOFILL";
field public static final String MANAGE_DEVICE_POLICY_BACKUP_SERVICE = "android.permission.MANAGE_DEVICE_POLICY_BACKUP_SERVICE";
- field @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled") public static final String MANAGE_DEVICE_POLICY_BLOCK_UNINSTALL = "android.permission.MANAGE_DEVICE_POLICY_BLOCK_UNINSTALL";
+ field public static final String MANAGE_DEVICE_POLICY_BLOCK_UNINSTALL = "android.permission.MANAGE_DEVICE_POLICY_BLOCK_UNINSTALL";
field public static final String MANAGE_DEVICE_POLICY_BLUETOOTH = "android.permission.MANAGE_DEVICE_POLICY_BLUETOOTH";
field public static final String MANAGE_DEVICE_POLICY_BUGREPORT = "android.permission.MANAGE_DEVICE_POLICY_BUGREPORT";
field public static final String MANAGE_DEVICE_POLICY_CALLS = "android.permission.MANAGE_DEVICE_POLICY_CALLS";
field public static final String MANAGE_DEVICE_POLICY_CAMERA = "android.permission.MANAGE_DEVICE_POLICY_CAMERA";
- field @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled") public static final String MANAGE_DEVICE_POLICY_CAMERA_TOGGLE = "android.permission.MANAGE_DEVICE_POLICY_CAMERA_TOGGLE";
+ field public static final String MANAGE_DEVICE_POLICY_CAMERA_TOGGLE = "android.permission.MANAGE_DEVICE_POLICY_CAMERA_TOGGLE";
field public static final String MANAGE_DEVICE_POLICY_CERTIFICATES = "android.permission.MANAGE_DEVICE_POLICY_CERTIFICATES";
field public static final String MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE = "android.permission.MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE";
field @FlaggedApi("android.view.contentprotection.flags.manage_device_policy_enabled") public static final String MANAGE_DEVICE_POLICY_CONTENT_PROTECTION = "android.permission.MANAGE_DEVICE_POLICY_CONTENT_PROTECTION";
@@ -172,7 +172,7 @@
field public static final String MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS = "android.permission.MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS";
field public static final String MANAGE_DEVICE_POLICY_METERED_DATA = "android.permission.MANAGE_DEVICE_POLICY_METERED_DATA";
field public static final String MANAGE_DEVICE_POLICY_MICROPHONE = "android.permission.MANAGE_DEVICE_POLICY_MICROPHONE";
- field @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled") public static final String MANAGE_DEVICE_POLICY_MICROPHONE_TOGGLE = "android.permission.MANAGE_DEVICE_POLICY_MICROPHONE_TOGGLE";
+ field public static final String MANAGE_DEVICE_POLICY_MICROPHONE_TOGGLE = "android.permission.MANAGE_DEVICE_POLICY_MICROPHONE_TOGGLE";
field public static final String MANAGE_DEVICE_POLICY_MOBILE_NETWORK = "android.permission.MANAGE_DEVICE_POLICY_MOBILE_NETWORK";
field public static final String MANAGE_DEVICE_POLICY_MODIFY_USERS = "android.permission.MANAGE_DEVICE_POLICY_MODIFY_USERS";
field public static final String MANAGE_DEVICE_POLICY_MTE = "android.permission.MANAGE_DEVICE_POLICY_MTE";
@@ -8121,7 +8121,7 @@
method public boolean isLogoutEnabled();
method public boolean isManagedProfile(@NonNull android.content.ComponentName);
method public boolean isMasterVolumeMuted(@NonNull android.content.ComponentName);
- method @FlaggedApi("android.app.admin.flags.is_mte_policy_enforced") public static boolean isMtePolicyEnforced();
+ method public static boolean isMtePolicyEnforced();
method public boolean isNetworkLoggingEnabled(@Nullable android.content.ComponentName);
method public boolean isOrganizationOwnedDeviceWithManagedProfile();
method public boolean isOverrideApnEnabled(@NonNull android.content.ComponentName);
@@ -8597,7 +8597,7 @@
field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
- field @FlaggedApi("android.app.admin.flags.backup_service_security_log_event_enabled") public static final int TAG_BACKUP_SERVICE_TOGGLED = 210044; // 0x3347c
+ field public static final int TAG_BACKUP_SERVICE_TOGGLED = 210044; // 0x3347c
field public static final int TAG_BLUETOOTH_CONNECTION = 210039; // 0x33477
field public static final int TAG_BLUETOOTH_DISCONNECTION = 210040; // 0x33478
field public static final int TAG_CAMERA_POLICY_SET = 210034; // 0x33472
@@ -43963,11 +43963,11 @@
field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT = "satellite_connection_hysteresis_sec_int";
field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_ENTITLEMENT_STATUS_REFRESH_DAYS_INT = "satellite_entitlement_status_refresh_days_int";
field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL = "satellite_entitlement_supported_bool";
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ESOS_INACTIVITY_TIMEOUT_SEC_INT = "satellite_esos_inactivity_timeout_sec_int";
field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ESOS_SUPPORTED_BOOL = "satellite_esos_supported_bool";
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT = "satellite_p2p_sms_inactivity_timeout_sec_int";
+ field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT = "satellite_roaming_esos_inactivity_timeout_sec_int";
+ field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT = "satellite_roaming_p2p_sms_inactivity_timeout_sec_int";
field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL = "satellite_roaming_p2p_sms_supported_bool";
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT = "satellite_screen_off_inactivity_timeout_sec_int";
+ field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT = "satellite_roaming_screen_off_inactivity_timeout_sec_int";
field public static final String KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL = "show_4g_for_3g_data_icon_bool";
field public static final String KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL = "show_4g_for_lte_data_icon_bool";
field public static final String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index ba16037..60dc52b 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1322,7 +1322,7 @@
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.UserHandle getDeviceOwnerUser();
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public android.app.admin.DevicePolicyState getDevicePolicyState();
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public String getFinancedDeviceKioskRoleHolder();
- method @FlaggedApi("android.app.admin.flags.device_policy_size_tracking_enabled") @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public int getMaxPolicyStorageLimit();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public int getMaxPolicyStorageLimit();
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_ADMIN_POLICY}) public java.util.List<java.lang.String> getPermittedAccessibilityServices(int);
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_ADMIN_POLICY}) public java.util.List<java.lang.String> getPermittedInputMethodsForCurrentUser();
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public java.util.List<android.os.UserHandle> getPolicyManagedProfiles(@NonNull android.os.UserHandle);
@@ -1349,7 +1349,7 @@
method @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_POLICY_AUDIT_LOGGING) public void setAuditLogEventCallback(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.List<android.app.admin.SecurityLog.SecurityEvent>>);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setDeviceProvisioningConfigApplied();
method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void setDpcDownloaded(boolean);
- method @FlaggedApi("android.app.admin.flags.device_policy_size_tracking_enabled") @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void setMaxPolicyStorageLimit(int);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void setMaxPolicyStorageLimit(int);
method @Deprecated @RequiresPermission(value=android.Manifest.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS, conditional=true) public void setProfileOwnerCanAccessDeviceIds(@NonNull android.content.ComponentName);
method public void setSecondaryLockscreenEnabled(@NonNull android.content.ComponentName, boolean);
method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void setUserProvisioningState(int, @NonNull android.os.UserHandle);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 42f7615..4fc7076 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2003,6 +2003,7 @@
method public void setRampingRingerEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) public void setRs2Value(float);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setTestDeviceConnectionState(@NonNull android.media.AudioDeviceAttributes, boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) public void setVolumeControllerLongPressTimeoutEnabled(boolean);
method @FlaggedApi("android.media.audio.focus_exclusive_with_recording") @RequiresPermission(android.Manifest.permission.QUERY_AUDIO_STATE) public boolean shouldNotificationSoundPlay(@NonNull android.media.AudioAttributes);
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 68063c4..b4fb480 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -66,6 +66,7 @@
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IpcDataCache;
import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcelable;
@@ -87,6 +88,7 @@
import android.view.WindowInsetsController.Appearance;
import android.window.TaskSnapshot;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.LocalePicker;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.os.RoSystemProperties;
@@ -237,6 +239,52 @@
private static final RateLimitingCache<List<ProcessErrorStateInfo>> mErrorProcessesCache =
new RateLimitingCache<>(10, 2);
+ /** Rate-Limiting cache that allows no more than 100 calls to the service per second. */
+ @GuardedBy("mMemoryInfoCache")
+ private static final RateLimitingCache<MemoryInfo> mMemoryInfoCache =
+ new RateLimitingCache<>(10);
+ /** Used to store cached results for rate-limited calls to getMemoryInfo(). */
+ @GuardedBy("mMemoryInfoCache")
+ private static final MemoryInfo mRateLimitedMemInfo = new MemoryInfo();
+
+ /**
+ * Query handler for mGetCurrentUserIdCache - returns a cached value of the current foreground
+ * user id if the backstage_power/android.app.cache_get_current_user_id flag is enabled.
+ */
+ private static final IpcDataCache.QueryHandler<Void, Integer> mGetCurrentUserIdQuery =
+ new IpcDataCache.QueryHandler<>() {
+ @Override
+ public Integer apply(Void query) {
+ try {
+ return getService().getCurrentUserId();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @Override
+ public boolean shouldBypassCache(Void query) {
+ // If the flag to enable the new caching behavior is off, bypass the cache.
+ return !Flags.cacheGetCurrentUserId();
+ }
+ };
+
+ /** A cache which maintains the current foreground user id. */
+ private static final IpcDataCache<Void, Integer> mGetCurrentUserIdCache =
+ new IpcDataCache<>(1, IpcDataCache.MODULE_SYSTEM,
+ /* api= */ "getCurrentUserId", /* cacheName= */ "CurrentUserIdCache",
+ mGetCurrentUserIdQuery);
+
+ /**
+ * The current foreground user has changed - invalidate the cache. Currently only called from
+ * UserController when a user switch occurs.
+ * @hide
+ */
+ public static void invalidateGetCurrentUserIdCache() {
+ IpcDataCache.invalidateCache(
+ IpcDataCache.MODULE_SYSTEM, /* api= */ "getCurrentUserId");
+ }
+
/**
* Map of callbacks that have registered for {@link UidFrozenStateChanged} events.
* Will be called when a Uid has become frozen or unfrozen.
@@ -3471,6 +3519,19 @@
foregroundAppThreshold = source.readLong();
}
+ /** @hide */
+ public void copyTo(MemoryInfo other) {
+ other.advertisedMem = advertisedMem;
+ other.availMem = availMem;
+ other.totalMem = totalMem;
+ other.threshold = threshold;
+ other.lowMemory = lowMemory;
+ other.hiddenAppThreshold = hiddenAppThreshold;
+ other.secondaryServerThreshold = secondaryServerThreshold;
+ other.visibleAppThreshold = visibleAppThreshold;
+ other.foregroundAppThreshold = foregroundAppThreshold;
+ }
+
public static final @android.annotation.NonNull Creator<MemoryInfo> CREATOR
= new Creator<MemoryInfo>() {
public MemoryInfo createFromParcel(Parcel source) {
@@ -3497,6 +3558,20 @@
* manage its memory.
*/
public void getMemoryInfo(MemoryInfo outInfo) {
+ if (Flags.rateLimitGetMemoryInfo()) {
+ synchronized (mMemoryInfoCache) {
+ mMemoryInfoCache.get(() -> {
+ getMemoryInfoInternal(mRateLimitedMemInfo);
+ return mRateLimitedMemInfo;
+ });
+ mRateLimitedMemInfo.copyTo(outInfo);
+ }
+ } else {
+ getMemoryInfoInternal(outInfo);
+ }
+ }
+
+ private void getMemoryInfoInternal(MemoryInfo outInfo) {
try {
getService().getMemoryInfo(outInfo);
} catch (RemoteException e) {
@@ -5244,11 +5319,7 @@
})
@android.ravenwood.annotation.RavenwoodReplace
public static int getCurrentUser() {
- try {
- return getService().getCurrentUserId();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return mGetCurrentUserIdCache.query(null);
}
/** @hide */
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 8fd3326..f27dc32 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -79,7 +79,6 @@
import android.provider.DeviceConfig;
import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.Log;
import android.util.LongSparseArray;
import android.util.LongSparseLongArray;
import android.util.Pools;
@@ -3156,12 +3155,6 @@
/** @hide */
public static final String KEY_HISTORICAL_OPS = "historical_ops";
- /** System properties for debug logging of noteOp call sites */
- private static final String DEBUG_LOGGING_ENABLE_PROP = "appops.logging_enabled";
- private static final String DEBUG_LOGGING_PACKAGES_PROP = "appops.logging_packages";
- private static final String DEBUG_LOGGING_OPS_PROP = "appops.logging_ops";
- private static final String DEBUG_LOGGING_TAG = "AppOpsManager";
-
/**
* Retrieve the op switch that controls the given operation.
* @hide
@@ -8066,14 +8059,6 @@
@RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setUidMode(int code, int uid, @Mode int mode) {
try {
- // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
- if (code == OP_BLUETOOTH_CONNECT) {
- Log.i(DEBUG_LOGGING_TAG,
- "setUidMode called for OP_BLUETOOTH_CONNECT with mode: " + mode
- + " for uid: " + uid + " calling uid: " + Binder.getCallingUid()
- + " trace: "
- + Arrays.toString(Thread.currentThread().getStackTrace()));
- }
mService.setUidMode(code, uid, mode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -8094,15 +8079,6 @@
@RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setUidMode(@NonNull String appOp, int uid, @Mode int mode) {
try {
- // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
- if (appOp.equals(OPSTR_BLUETOOTH_CONNECT)) {
- Log.i(DEBUG_LOGGING_TAG,
- "setUidMode called for OPSTR_BLUETOOTH_CONNECT with mode: " + mode
- + " for uid: " + uid + " calling uid: " + Binder.getCallingUid()
- + " trace: "
- + Arrays.toString(Thread.currentThread().getStackTrace()));
- }
-
mService.setUidMode(AppOpsManager.strOpToOp(appOp), uid, mode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -8143,14 +8119,6 @@
@RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
public void setMode(int code, int uid, String packageName, @Mode int mode) {
try {
- // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
- if (code == OP_BLUETOOTH_CONNECT) {
- Log.i(DEBUG_LOGGING_TAG,
- "setMode called for OPSTR_BLUETOOTH_CONNECT with mode: " + mode
- + " for uid: " + uid + " calling uid: " + Binder.getCallingUid()
- + " trace: "
- + Arrays.toString(Thread.currentThread().getStackTrace()));
- }
mService.setMode(code, uid, packageName, mode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -8173,14 +8141,6 @@
public void setMode(@NonNull String op, int uid, @Nullable String packageName,
@Mode int mode) {
try {
- // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
- if (op.equals(OPSTR_BLUETOOTH_CONNECT)) {
- Log.i(DEBUG_LOGGING_TAG,
- "setMode called for OPSTR_BLUETOOTH_CONNECT with mode: " + mode
- + " for uid: " + uid + " calling uid: " + Binder.getCallingUid()
- + " trace: "
- + Arrays.toString(Thread.currentThread().getStackTrace()));
- }
mService.setMode(strOpToOp(op), uid, packageName, mode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 789c99d..1b29b7a 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -168,7 +168,11 @@
/**
* @hide
*/
- public static final int MAX_VIBRATION_LENGTH = 1000;
+ public static final int MAX_VIBRATION_LENGTH = 500;
+ /**
+ * @hide
+ */
+ public static final int MAX_SERIALIZED_VIBRATION_LENGTH = 32_768;
private static final String TAG_CHANNEL = "channel";
private static final String ATT_NAME = "name";
@@ -368,6 +372,9 @@
if (Flags.notificationChannelVibrationEffectApi()) {
mVibrationEffect =
in.readInt() != 0 ? VibrationEffect.CREATOR.createFromParcel(in) : null;
+ if (Flags.notifChannelCropVibrationEffects() && mVibrationEffect != null) {
+ mVibrationEffect = getTrimmedVibrationEffect(mVibrationEffect);
+ }
}
mUserLockedFields = in.readInt();
mUserVisibleTaskShown = in.readByte() != 0;
@@ -582,6 +589,23 @@
return input;
}
+ // Returns trimmed vibration effect or null if not trimmable.
+ private VibrationEffect getTrimmedVibrationEffect(VibrationEffect effect) {
+ if (effect == null) {
+ return null;
+ }
+ // trim if possible; check serialized length; reject if it is still too long
+ VibrationEffect result = effect;
+ VibrationEffect trimmed = effect.cropToLengthOrNull(MAX_VIBRATION_LENGTH);
+ if (trimmed != null) {
+ result = trimmed;
+ }
+ if (vibrationToString(result).length() > MAX_SERIALIZED_VIBRATION_LENGTH) {
+ return null;
+ }
+ return result;
+ }
+
/**
* @hide
*/
@@ -685,6 +709,11 @@
public void setVibrationPattern(long[] vibrationPattern) {
this.mVibrationEnabled = vibrationPattern != null && vibrationPattern.length > 0;
this.mVibrationPattern = vibrationPattern;
+ if (Flags.notifChannelCropVibrationEffects()) {
+ if (vibrationPattern != null && vibrationPattern.length > MAX_VIBRATION_LENGTH) {
+ this.mVibrationPattern = Arrays.copyOf(vibrationPattern, MAX_VIBRATION_LENGTH);
+ }
+ }
if (Flags.notificationChannelVibrationEffectApi()) {
try {
this.mVibrationEffect =
@@ -731,9 +760,21 @@
public void setVibrationEffect(@Nullable VibrationEffect effect) {
this.mVibrationEnabled = effect != null;
this.mVibrationEffect = effect;
- this.mVibrationPattern =
- effect == null
- ? null : effect.computeCreateWaveformOffOnTimingsOrNull();
+ if (Flags.notifChannelCropVibrationEffects() && effect != null) {
+ // Try converting to a vibration pattern and trimming that array. If not convertible
+ // to a pattern directly, try trimming the vibration effect if possible and storing
+ // that version instead.
+ long[] pattern = effect.computeCreateWaveformOffOnTimingsOrNull();
+ if (pattern != null) {
+ setVibrationPattern(pattern);
+ } else {
+ this.mVibrationEffect = getTrimmedVibrationEffect(mVibrationEffect);
+ }
+ } else {
+ this.mVibrationPattern =
+ mVibrationEffect == null
+ ? null : mVibrationEffect.computeCreateWaveformOffOnTimingsOrNull();
+ }
}
/**
@@ -1172,7 +1213,9 @@
if (vibrationEffect != null) {
// Restore the effect only if it is not null. This allows to avoid undoing a
// `setVibrationPattern` call above, if that was done with a non-null pattern
- // (e.g. back up from a version that did not support `setVibrationEffect`).
+ // (e.g. back up from a version that did not support `setVibrationEffect`), or
+ // when notif_channel_crop_vibration_effects is true, if there is an equivalent
+ // vibration pattern available.
setVibrationEffect(vibrationEffect);
}
}
@@ -1365,7 +1408,11 @@
out.attribute(null, ATT_VIBRATION, longArrayToString(getVibrationPattern()));
}
if (getVibrationEffect() != null) {
- out.attribute(null, ATT_VIBRATION_EFFECT, vibrationToString(getVibrationEffect()));
+ if (!Flags.notifChannelCropVibrationEffects() || getVibrationPattern() == null) {
+ // When notif_channel_crop_vibration_effects is on, only serialize the vibration
+ // effect if we do not already have an equivalent vibration pattern.
+ out.attribute(null, ATT_VIBRATION_EFFECT, vibrationToString(getVibrationEffect()));
+ }
}
if (getUserLockedFields() != 0) {
out.attributeInt(null, ATT_USER_LOCKED, getUserLockedFields());
diff --git a/core/java/android/app/activity_manager.aconfig b/core/java/android/app/activity_manager.aconfig
index 32e6e80..c0c81df 100644
--- a/core/java/android/app/activity_manager.aconfig
+++ b/core/java/android/app/activity_manager.aconfig
@@ -104,3 +104,35 @@
}
}
+flag {
+ namespace: "backstage_power"
+ name: "use_app_info_not_launched"
+ description: "Use the notLaunched state from ApplicationInfo instead of current value"
+ is_fixed_read_only: true
+ bug: "362516211"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ namespace: "backstage_power"
+ name: "cache_get_current_user_id"
+ description: "Add caching for getCurrentUserId"
+ is_fixed_read_only: true
+ bug: "361853873"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ namespace: "backstage_power"
+ name: "rate_limit_get_memory_info"
+ description: "Rate limit calls to getMemoryInfo using a cache"
+ is_fixed_read_only: true
+ bug: "364312431"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index 4f2efa4..cb2b8ad 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -18,7 +18,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.app.admin.flags.Flags;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
@@ -388,11 +387,8 @@
}
mSupportsTransferOwnership = true;
} else if (tagName.equals("headless-system-user")) {
- String deviceOwnerModeStringValue = null;
- if (Flags.headlessSingleUserCompatibilityFix()) {
- deviceOwnerModeStringValue = parser.getAttributeValue(
- null, "headless-device-owner-mode");
- }
+ String deviceOwnerModeStringValue = parser.getAttributeValue(
+ null, "headless-device-owner-mode");
if (deviceOwnerModeStringValue == null) {
deviceOwnerModeStringValue =
parser.getAttributeValue(null, "device-owner-mode");
@@ -405,13 +401,8 @@
} else if ("single_user".equalsIgnoreCase(deviceOwnerModeStringValue)) {
mHeadlessDeviceOwnerMode = HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER;
} else {
- if (Flags.headlessSingleUserCompatibilityFix()) {
- Log.e(TAG, "Unknown headless-system-user mode: "
- + deviceOwnerModeStringValue);
- } else {
- throw new XmlPullParserException(
- "headless-system-user mode must be valid");
- }
+ Log.e(TAG, "Unknown headless-system-user mode: "
+ + deviceOwnerModeStringValue);
}
}
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 1ddec17..daa15f0 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -55,10 +55,8 @@
import static android.Manifest.permission.SET_TIME_ZONE;
import static android.app.admin.DeviceAdminInfo.HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED;
import static android.app.admin.flags.Flags.FLAG_DEVICE_THEFT_API_ENABLED;
-import static android.app.admin.flags.Flags.FLAG_DEVICE_POLICY_SIZE_TRACKING_ENABLED;
import static android.app.admin.flags.Flags.onboardingBugreportV2Enabled;
import static android.app.admin.flags.Flags.onboardingConsentlessBugreports;
-import static android.app.admin.flags.Flags.FLAG_IS_MTE_POLICY_ENFORCED;
import static android.content.Intent.LOCAL_FLAG_FROM_SYSTEM;
import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
@@ -4232,7 +4230,6 @@
*
* @return whether MTE is currently enabled on the device.
*/
- @FlaggedApi(FLAG_IS_MTE_POLICY_ENFORCED)
public static boolean isMtePolicyEnforced() {
return Zygote.nativeSupportsMemoryTagging();
}
@@ -8664,6 +8661,7 @@
* {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA}.
*/
@RequiresPermission(value = MANAGE_DEVICE_POLICY_CAMERA, conditional = true)
+ @SupportsCoexistence
public void setCameraDisabled(@Nullable ComponentName admin, boolean disabled) {
if (mService != null) {
try {
@@ -10249,6 +10247,7 @@
* permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_LOCK_TASK}.
*/
@RequiresPermission(value = MANAGE_DEVICE_POLICY_LOCK_TASK, conditional = true)
+ @SupportsCoexistence
public void clearPackagePersistentPreferredActivities(@Nullable ComponentName admin,
String packageName) {
throwIfParentInstance("clearPackagePersistentPreferredActivities");
@@ -10476,10 +10475,6 @@
@WorkerThread
public void setApplicationRestrictions(@Nullable ComponentName admin, String packageName,
Bundle settings) {
- if (!Flags.dmrhSetAppRestrictions()) {
- throwIfParentInstance("setApplicationRestrictions");
- }
-
if (mService != null) {
try {
mService.setApplicationRestrictions(admin, mContext.getPackageName(), packageName,
@@ -11884,9 +11879,6 @@
@WorkerThread
public @NonNull Bundle getApplicationRestrictions(
@Nullable ComponentName admin, String packageName) {
- if (!Flags.dmrhSetAppRestrictions()) {
- throwIfParentInstance("getApplicationRestrictions");
- }
if (mService != null) {
try {
@@ -11947,6 +11939,7 @@
* @throws SecurityException if {@code admin} is not a device or profile owner and if the caller
* has not been granted the permission to set the given user restriction.
*/
+ @SupportsCoexistence
public void addUserRestriction(@NonNull ComponentName admin,
@UserManager.UserRestrictionKey String key) {
if (mService != null) {
@@ -12028,6 +12021,7 @@
* @throws IllegalStateException if caller is not targeting Android
* {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or above.
*/
+ @SupportsCoexistence
public void addUserRestrictionGlobally(@NonNull @UserManager.UserRestrictionKey String key) {
throwIfParentInstance("addUserRestrictionGlobally");
if (mService != null) {
@@ -12083,6 +12077,7 @@
* @throws SecurityException if {@code admin} is not a device or profile owner and if the
* caller has not been granted the permission to set the given user restriction.
*/
+ @SupportsCoexistence
public void clearUserRestriction(@NonNull ComponentName admin,
@UserManager.UserRestrictionKey String key) {
if (mService != null) {
@@ -12319,6 +12314,7 @@
* @see #DELEGATION_PACKAGE_ACCESS
*/
@RequiresPermission(value = MANAGE_DEVICE_POLICY_PACKAGE_STATE, conditional = true)
+ @SupportsCoexistence
public boolean setApplicationHidden(@Nullable ComponentName admin, String packageName,
boolean hidden) {
if (mService != null) {
@@ -12499,6 +12495,7 @@
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
@RequiresPermission(value = MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT, conditional = true)
+ @SupportsCoexistence
public void setAccountManagementDisabled(@Nullable ComponentName admin, String accountType,
boolean disabled) {
if (mService != null) {
@@ -12582,10 +12579,24 @@
**/
@SystemApi
public void setSecondaryLockscreenEnabled(@NonNull ComponentName admin, boolean enabled) {
+ setSecondaryLockscreenEnabled(admin, enabled, null);
+ }
+
+ /**
+ * Called by the system supervision app to set whether a secondary lockscreen needs to be shown.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
+ * caller is not a device admin.
+ * @param enabled Whether or not the lockscreen needs to be shown.
+ * @param options A {@link PersistableBundle} to supply options to the lock screen.
+ * @hide
+ */
+ public void setSecondaryLockscreenEnabled(@Nullable ComponentName admin, boolean enabled,
+ @Nullable PersistableBundle options) {
throwIfParentInstance("setSecondaryLockscreenEnabled");
if (mService != null) {
try {
- mService.setSecondaryLockscreenEnabled(admin, enabled);
+ mService.setSecondaryLockscreenEnabled(admin, enabled, options);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -14231,21 +14242,11 @@
*/
public @NonNull DevicePolicyManager getParentProfileInstance(@NonNull ComponentName admin) {
throwIfParentInstance("getParentProfileInstance");
- try {
- if (Flags.dmrhSetAppRestrictions()) {
- UserManager um = mContext.getSystemService(UserManager.class);
- if (!um.isManagedProfile()) {
- throw new SecurityException("The current user does not have a parent profile.");
- }
- } else {
- if (!mService.isManagedProfile(admin)) {
- throw new SecurityException("The current user does not have a parent profile.");
- }
- }
- return new DevicePolicyManager(mContext, mService, true);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ UserManager um = mContext.getSystemService(UserManager.class);
+ if (!um.isManagedProfile()) {
+ throw new SecurityException("The current user does not have a parent profile.");
}
+ return new DevicePolicyManager(mContext, mService, true);
}
/**
@@ -14293,6 +14294,7 @@
* @see #retrieveSecurityLogs
*/
@RequiresPermission(value = MANAGE_DEVICE_POLICY_SECURITY_LOGGING, conditional = true)
+ @SupportsCoexistence
public void setSecurityLoggingEnabled(@Nullable ComponentName admin, boolean enabled) {
throwIfParentInstance("setSecurityLoggingEnabled");
try {
@@ -17198,6 +17200,7 @@
* if USB data signaling fails to be enabled/disabled.
*/
@RequiresPermission(value = MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING, conditional = true)
+ @SupportsCoexistence
public void setUsbDataSignalingEnabled(boolean enabled) {
throwIfParentInstance("setUsbDataSignalingEnabled");
if (mService != null) {
@@ -17763,7 +17766,6 @@
*/
@SystemApi
@RequiresPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
- @FlaggedApi(FLAG_DEVICE_POLICY_SIZE_TRACKING_ENABLED)
public void setMaxPolicyStorageLimit(int storageLimit) {
if (mService != null) {
try {
@@ -17783,7 +17785,6 @@
*/
@SystemApi
@RequiresPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
- @FlaggedApi(FLAG_DEVICE_POLICY_SIZE_TRACKING_ENABLED)
public int getMaxPolicyStorageLimit() {
if (mService != null) {
try {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index d4e5c99..a4e2b8f 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -303,7 +303,7 @@
String[] getAccountTypesWithManagementDisabled(String callerPackageName);
String[] getAccountTypesWithManagementDisabledAsUser(int userId, String callerPackageName, in boolean parent);
- void setSecondaryLockscreenEnabled(in ComponentName who, boolean enabled);
+ void setSecondaryLockscreenEnabled(in ComponentName who, boolean enabled, in PersistableBundle options);
boolean isSecondaryLockscreenEnabled(in UserHandle userHandle);
void setPreferentialNetworkServiceConfigs(
diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
index 477f2e0..beb93fd 100644
--- a/core/java/android/app/admin/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -16,10 +16,7 @@
package android.app.admin;
-import static android.app.admin.flags.Flags.FLAG_BACKUP_SERVICE_SECURITY_LOG_EVENT_ENABLED;
-
import android.Manifest;
-import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -611,7 +608,6 @@
* <li> [2] backup service state ({@code Integer}, 1 for enabled, 0 for disabled)
* @see DevicePolicyManager#setBackupServiceEnabled(ComponentName, boolean)
*/
- @FlaggedApi(FLAG_BACKUP_SERVICE_SECURITY_LOG_EVENT_ENABLED)
public static final int TAG_BACKUP_SERVICE_TOGGLED =
SecurityLogTags.SECURITY_BACKUP_SERVICE_TOGGLED;
/**
diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig
index d9bd77f..8e08a95 100644
--- a/core/java/android/app/admin/flags/flags.aconfig
+++ b/core/java/android/app/admin/flags/flags.aconfig
@@ -13,6 +13,7 @@
bug: "289520697"
}
+# Fully rolled out and must not be used.
flag {
name: "device_policy_size_tracking_enabled"
is_exported: true
@@ -22,13 +23,6 @@
}
flag {
- name: "device_policy_size_tracking_internal_enabled"
- namespace: "enterprise"
- description: "Add feature to track the total policy size and have a max threshold - internal changes"
- bug: "281543351"
-}
-
-flag {
name: "onboarding_bugreport_v2_enabled"
is_exported: true
namespace: "enterprise"
@@ -44,13 +38,7 @@
is_fixed_read_only: true
}
-flag {
- name: "dedicated_device_control_enabled"
- namespace: "enterprise"
- description: "Allow the device management role holder to control which platform features are available on dedicated devices."
- bug: "281964214"
-}
-
+# Fully rolled out and must not be used.
flag {
name: "dedicated_device_control_api_enabled"
is_exported: true
@@ -83,13 +71,6 @@
}
flag {
- name: "coexistence_migration_for_non_emm_management_enabled"
- namespace: "enterprise"
- description: "Migrate existing APIs to be coexistable, and enable DMRH to call them to support non-EMM device management."
- bug: "289520697"
-}
-
-flag {
name: "coexistence_migration_for_supervision_enabled"
is_exported: true
namespace: "enterprise"
@@ -97,6 +78,62 @@
bug: "356894721"
}
+flag {
+ name: "reset_password_with_token_coexistence"
+ is_exported: true
+ namespace: "enterprise"
+ description: "Enables coexistence support for resetPasswordWithToken and setResetPasswordToken."
+ bug: "359187209"
+}
+
+flag {
+ name: "set_keyguard_disabled_features_coexistence"
+ is_exported: true
+ namespace: "enterprise"
+ description: "Enables coexistence support for setKeyguardDisabledFeatures."
+ bug: "359186276"
+}
+
+flag {
+ name: "set_application_restrictions_coexistence"
+ is_exported: true
+ namespace: "enterprise"
+ description: "Enables coexistence support for setApplicationRestrictions."
+ bug: "359188153"
+}
+
+flag {
+ name: "set_auto_time_enabled_coexistence"
+ is_exported: true
+ namespace: "enterprise"
+ description: "Enables coexistence support for setAutoTimeEnabled."
+ bug: "359188869"
+}
+
+flag {
+ name: "set_backup_service_enabled_coexistence"
+ is_exported: true
+ namespace: "enterprise"
+ description: "Enables coexistence support for setBackupServiceEnabled."
+ bug: "359188483"
+}
+
+flag {
+ name: "set_auto_time_zone_enabled_coexistence"
+ is_exported: true
+ namespace: "enterprise"
+ description: "Enables coexistence support for setAutoTimeZoneEnabled."
+ bug: "364338300"
+}
+
+flag {
+ name: "set_permission_grant_state_coexistence"
+ is_exported: true
+ namespace: "enterprise"
+ description: "Enables coexistence support for setPermissionGrantState."
+ bug: "364338410"
+}
+
# Fully rolled out and must not be used.
flag {
name: "security_log_v2_enabled"
@@ -107,16 +144,6 @@
}
flag {
- name: "hsum_unlock_notification_fix"
- namespace: "enterprise"
- description: "Using the right userId when starting the work profile unlock flow "
- bug: "327350831"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "allow_querying_profile_type"
is_exported: true
namespace: "enterprise"
@@ -131,6 +158,7 @@
bug: "293441361"
}
+# Fully rolled out and must not be used.
flag {
name: "assist_content_user_restriction_enabled"
is_exported: true
@@ -149,6 +177,7 @@
}
}
+# Fully rolled out and must not be used.
flag {
name: "backup_service_security_log_event_enabled"
is_exported: true
@@ -157,6 +186,7 @@
bug: "304999634"
}
+# Fully rolled out and must not be used.
flag {
name: "esim_management_enabled"
is_exported: true
@@ -174,6 +204,7 @@
bug: "289515470"
}
+# Fully rolled out and must not be used.
flag {
name: "is_mte_policy_enforced"
is_exported: true
@@ -183,16 +214,6 @@
}
flag {
- name: "copy_account_with_retry_enabled"
- namespace: "enterprise"
- description: "Retry copy and remove account from personal to work profile in case of failure"
- bug: "329424312"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "disallow_user_control_stopped_state_fix"
namespace: "enterprise"
description: "Ensure DPM.setUserControlDisabledPackages() clears FLAG_STOPPED for the app"
@@ -210,26 +231,6 @@
}
flag {
- name: "dmrh_set_app_restrictions"
- namespace: "enterprise"
- description: "Allow DMRH to set application restrictions (both on the profile and the parent)"
- bug: "328758346"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
- name: "always_persist_do"
- namespace: "enterprise"
- description: "Always write device_owners2.xml so that migration flags aren't lost"
- bug: "335232744"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "is_recursive_required_app_merging_enabled"
namespace: "enterprise"
description: "Guards a new flow for recursive required enterprise app list merging"
@@ -237,16 +238,6 @@
}
flag {
- name: "headless_single_user_bad_device_admin_state_fix"
- namespace: "enterprise"
- description: "Fix the bad state in DPMS caused by an earlier bug related to the headless single user change"
- bug: "332477138"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "onboarding_bugreport_storage_bug_fix"
namespace: "enterprise"
description: "Add a separate storage limit for deferred bugreports"
@@ -267,16 +258,6 @@
}
flag {
- name: "headless_single_user_fixes"
- namespace: "enterprise"
- description: "Various fixes for headless single user mode"
- bug: "289515470"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "backup_connected_apps_settings"
namespace: "enterprise"
description: "backup and restore connected work and personal apps user settings across devices"
@@ -284,16 +265,6 @@
}
flag {
- name: "headless_single_user_compatibility_fix"
- namespace: "enterprise"
- description: "Fix for compatibility issue introduced from using single_user mode on pre-Android V builds"
- bug: "338050276"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "headless_single_min_target_sdk"
namespace: "enterprise"
description: "Only allow DPCs targeting Android V to provision into single user mode"
diff --git a/core/java/android/app/appfunctions/AppFunctionManager.java b/core/java/android/app/appfunctions/AppFunctionManager.java
index 8f609de..4682f3d 100644
--- a/core/java/android/app/appfunctions/AppFunctionManager.java
+++ b/core/java/android/app/appfunctions/AppFunctionManager.java
@@ -50,7 +50,7 @@
* Creates an instance.
*
* @param service An interface to the backing service.
- * @param context A {@link Context}.
+ * @param context A {@link Context}.
* @hide
*/
public AppFunctionManager(IAppFunctionManager service, Context context) {
@@ -60,42 +60,42 @@
/**
* Executes the app function.
- * <p>
- * Note: Applications can execute functions they define. To execute functions defined in
- * another component, apps would need to have
- * {@code android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or
- * {@code android.permission.EXECUTE_APP_FUNCTIONS}.
*
- * @param request the request to execute the app function
+ * <p>Note: Applications can execute functions they define. To execute functions defined in
+ * another component, apps would need to have {@code
+ * android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or {@code
+ * android.permission.EXECUTE_APP_FUNCTIONS}.
+ *
+ * @param request the request to execute the app function
* @param executor the executor to run the callback
* @param callback the callback to receive the function execution result. if the calling app
- * does not own the app function or does not have {@code
- * android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or {@code
- * android.permission.EXECUTE_APP_FUNCTIONS}, the execution result will contain
- * {@code ExecuteAppFunctionResponse.RESULT_DENIED}.
+ * does not own the app function or does not have {@code
+ * android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or {@code
+ * android.permission.EXECUTE_APP_FUNCTIONS}, the execution result will contain {@code
+ * ExecuteAppFunctionResponse.RESULT_DENIED}.
*/
// TODO(b/360864791): Document that apps can opt-out from being executed by callers with
// EXECUTE_APP_FUNCTIONS and how a caller knows whether a function is opted out.
// TODO(b/357551503): Update documentation when get / set APIs are implemented that this will
// also return RESULT_DENIED if the app function is disabled.
@RequiresPermission(
- anyOf = {Manifest.permission.EXECUTE_APP_FUNCTIONS_TRUSTED,
- Manifest.permission.EXECUTE_APP_FUNCTIONS}, conditional = true)
+ anyOf = {
+ Manifest.permission.EXECUTE_APP_FUNCTIONS_TRUSTED,
+ Manifest.permission.EXECUTE_APP_FUNCTIONS
+ },
+ conditional = true)
@UserHandleAware
public void executeAppFunction(
@NonNull ExecuteAppFunctionRequest request,
@NonNull @CallbackExecutor Executor executor,
- @NonNull Consumer<ExecuteAppFunctionResponse> callback
- ) {
+ @NonNull Consumer<ExecuteAppFunctionResponse> callback) {
Objects.requireNonNull(request);
Objects.requireNonNull(executor);
Objects.requireNonNull(callback);
ExecuteAppFunctionAidlRequest aidlRequest =
new ExecuteAppFunctionAidlRequest(
- request,
- mContext.getUser(),
- mContext.getPackageName());
+ request, mContext.getUser(), mContext.getPackageName());
try {
mService.executeAppFunction(
aidlRequest,
@@ -107,8 +107,11 @@
} catch (RuntimeException e) {
// Ideally shouldn't happen since errors are wrapped into the
// response, but we catch it here for additional safety.
- callback.accept(ExecuteAppFunctionResponse.newFailure(
- getResultCode(e), e.getMessage(), /*extras=*/ null));
+ callback.accept(
+ ExecuteAppFunctionResponse.newFailure(
+ getResultCode(e),
+ e.getMessage(),
+ /* extras= */ null));
}
}
});
diff --git a/core/java/android/app/appfunctions/AppFunctionManagerConfiguration.java b/core/java/android/app/appfunctions/AppFunctionManagerConfiguration.java
index e4784b4..fa77e79 100644
--- a/core/java/android/app/appfunctions/AppFunctionManagerConfiguration.java
+++ b/core/java/android/app/appfunctions/AppFunctionManagerConfiguration.java
@@ -23,8 +23,8 @@
import android.content.pm.PackageManager;
/**
- * Represents the system configuration of support for the {@code AppFunctionManager} and
- * associated systems.
+ * Represents the system configuration of support for the {@code AppFunctionManager} and associated
+ * systems.
*
* @hide
*/
@@ -33,6 +33,7 @@
/**
* Constructs a new instance of {@code AppFunctionManagerConfiguration}.
+ *
* @param context context
*/
public AppFunctionManagerConfiguration(@NonNull final Context context) {
@@ -41,15 +42,16 @@
/**
* Indicates whether the current target is intended to support {@code AppFunctionManager}.
+ *
* @return {@code true} if supported; otherwise {@code false}
*/
public boolean isSupported() {
return enableAppFunctionManager() && !isWatch();
-
}
/**
* Indicates whether the current target is intended to support {@code AppFunctionManager}.
+ *
* @param context context
* @return {@code true} if supported; otherwise {@code false}
*/
diff --git a/core/java/android/app/appfunctions/AppFunctionManagerHelper.java b/core/java/android/app/appfunctions/AppFunctionManagerHelper.java
index 3169f0e..d6f45e4 100644
--- a/core/java/android/app/appfunctions/AppFunctionManagerHelper.java
+++ b/core/java/android/app/appfunctions/AppFunctionManagerHelper.java
@@ -49,25 +49,25 @@
/**
* Returns (through a callback) a boolean indicating whether the app function is enabled.
- * <p>
- * This method can only check app functions that are owned by the caller owned by packages
+ *
+ * <p>This method can only check app functions that are owned by the caller owned by packages
* visible to the caller.
- * <p>
- * If operation fails, the callback's {@link OutcomeReceiver#onError} is called with errors:
+ *
+ * <p>If operation fails, the callback's {@link OutcomeReceiver#onError} is called with errors:
+ *
* <ul>
- * <li>{@link IllegalArgumentException}, if the function is not found</li>
- * <li>{@link SecurityException}, if the caller does not have permission to query the
- * target package
- * </li>
- * </ul>
+ * <li>{@link IllegalArgumentException}, if the function is not found
+ * <li>{@link SecurityException}, if the caller does not have permission to query the target
+ * package
+ * </ul>
*
* @param functionIdentifier the identifier of the app function to check (unique within the
- * target package) and in most cases, these are automatically
- * generated by the AppFunctions SDK
- * @param targetPackage the package name of the app function's owner
- * @param appSearchExecutor the executor to run the metadata search mechanism through AppSearch
- * @param callbackExecutor the executor to run the callback
- * @param callback the callback to receive the function enabled check result
+ * target package) and in most cases, these are automatically generated by the AppFunctions
+ * SDK
+ * @param targetPackage the package name of the app function's owner
+ * @param appSearchExecutor the executor to run the metadata search mechanism through AppSearch
+ * @param callbackExecutor the executor to run the callback
+ * @param callback the callback to receive the function enabled check result
* @hide
*/
public static void isAppFunctionEnabled(
@@ -76,8 +76,7 @@
@NonNull AppSearchManager appSearchManager,
@NonNull Executor appSearchExecutor,
@NonNull @CallbackExecutor Executor callbackExecutor,
- @NonNull OutcomeReceiver<Boolean, Exception> callback
- ) {
+ @NonNull OutcomeReceiver<Boolean, Exception> callback) {
Objects.requireNonNull(functionIdentifier);
Objects.requireNonNull(targetPackage);
Objects.requireNonNull(appSearchManager);
@@ -85,27 +84,37 @@
Objects.requireNonNull(callbackExecutor);
Objects.requireNonNull(callback);
- appSearchManager.createGlobalSearchSession(appSearchExecutor,
+ appSearchManager.createGlobalSearchSession(
+ appSearchExecutor,
(searchSessionResult) -> {
if (!searchSessionResult.isSuccess()) {
- callbackExecutor.execute(() ->
- callback.onError(failedResultToException(searchSessionResult)));
+ callbackExecutor.execute(
+ () ->
+ callback.onError(
+ failedResultToException(searchSessionResult)));
return;
}
try (GlobalSearchSession searchSession = searchSessionResult.getResultValue()) {
- SearchResults results = searchJoinedStaticWithRuntimeAppFunctions(
- searchSession, targetPackage, functionIdentifier);
- results.getNextPage(appSearchExecutor,
- listAppSearchResult -> callbackExecutor.execute(() -> {
- if (listAppSearchResult.isSuccess()) {
- callback.onResult(getEnabledStateFromSearchResults(
- Objects.requireNonNull(
- listAppSearchResult.getResultValue())));
- } else {
- callback.onError(
- failedResultToException(listAppSearchResult));
- }
- }));
+ SearchResults results =
+ searchJoinedStaticWithRuntimeAppFunctions(
+ searchSession, targetPackage, functionIdentifier);
+ results.getNextPage(
+ appSearchExecutor,
+ listAppSearchResult ->
+ callbackExecutor.execute(
+ () -> {
+ if (listAppSearchResult.isSuccess()) {
+ callback.onResult(
+ getEnabledStateFromSearchResults(
+ Objects.requireNonNull(
+ listAppSearchResult
+ .getResultValue())));
+ } else {
+ callback.onError(
+ failedResultToException(
+ listAppSearchResult));
+ }
+ }));
} catch (Exception e) {
callbackExecutor.execute(() -> callback.onError(e));
}
@@ -122,27 +131,27 @@
@NonNull GlobalSearchSession session,
@NonNull String targetPackage,
@NonNull String functionIdentifier) {
- SearchSpec runtimeSearchSpec = getAppFunctionRuntimeMetadataSearchSpecByFunctionId(
- targetPackage);
- JoinSpec joinSpec = new JoinSpec.Builder(
- PROPERTY_APP_FUNCTION_STATIC_METADATA_QUALIFIED_ID)
- .setNestedSearch(
- functionIdentifier,
- runtimeSearchSpec).build();
- SearchSpec joinedStaticWithRuntimeSearchSpec = new SearchSpec.Builder()
- .setJoinSpec(joinSpec)
- .addFilterPackageNames(APP_FUNCTION_INDEXER_PACKAGE)
- .addFilterSchemas(
- AppFunctionStaticMetadataHelper.getStaticSchemaNameForPackage(
- targetPackage))
- .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
- .build();
+ SearchSpec runtimeSearchSpec =
+ getAppFunctionRuntimeMetadataSearchSpecByFunctionId(targetPackage);
+ JoinSpec joinSpec =
+ new JoinSpec.Builder(PROPERTY_APP_FUNCTION_STATIC_METADATA_QUALIFIED_ID)
+ .setNestedSearch(functionIdentifier, runtimeSearchSpec)
+ .build();
+ SearchSpec joinedStaticWithRuntimeSearchSpec =
+ new SearchSpec.Builder()
+ .setJoinSpec(joinSpec)
+ .addFilterPackageNames(APP_FUNCTION_INDEXER_PACKAGE)
+ .addFilterSchemas(
+ AppFunctionStaticMetadataHelper.getStaticSchemaNameForPackage(
+ targetPackage))
+ .setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
+ .build();
return session.search(functionIdentifier, joinedStaticWithRuntimeSearchSpec);
}
/**
- * Finds whether the function is enabled or not from the search results returned by
- * {@link #searchJoinedStaticWithRuntimeAppFunctions}.
+ * Finds whether the function is enabled or not from the search results returned by {@link
+ * #searchJoinedStaticWithRuntimeAppFunctions}.
*
* @throws IllegalArgumentException if the function is not found in the results
* @hide
@@ -156,15 +165,20 @@
List<SearchResult> runtimeMetadataResults =
joinedStaticRuntimeResults.getFirst().getJoinedResults();
if (!runtimeMetadataResults.isEmpty()) {
- Boolean result = (Boolean) runtimeMetadataResults
- .getFirst().getGenericDocument()
- .getProperty(PROPERTY_ENABLED);
+ Boolean result =
+ (Boolean)
+ runtimeMetadataResults
+ .getFirst()
+ .getGenericDocument()
+ .getProperty(PROPERTY_ENABLED);
if (result != null) {
return result;
}
}
// Runtime metadata not found. Using the default value in the static metadata.
- return joinedStaticRuntimeResults.getFirst().getGenericDocument()
+ return joinedStaticRuntimeResults
+ .getFirst()
+ .getGenericDocument()
.getPropertyBoolean(STATIC_PROPERTY_ENABLED_BY_DEFAULT);
}
}
@@ -180,11 +194,9 @@
return new SearchSpec.Builder()
.addFilterPackageNames(APP_FUNCTION_INDEXER_PACKAGE)
.addFilterSchemas(
- AppFunctionRuntimeMetadata.getRuntimeSchemaNameForPackage(
- targetPackage))
+ AppFunctionRuntimeMetadata.getRuntimeSchemaNameForPackage(targetPackage))
.addFilterProperties(
- AppFunctionRuntimeMetadata.getRuntimeSchemaNameForPackage(
- targetPackage),
+ AppFunctionRuntimeMetadata.getRuntimeSchemaNameForPackage(targetPackage),
List.of(AppFunctionRuntimeMetadata.PROPERTY_FUNCTION_ID))
.setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
.build();
@@ -198,12 +210,12 @@
public static @NonNull Exception failedResultToException(
@NonNull AppSearchResult appSearchResult) {
return switch (appSearchResult.getResultCode()) {
- case AppSearchResult.RESULT_INVALID_ARGUMENT -> new IllegalArgumentException(
- appSearchResult.getErrorMessage());
- case AppSearchResult.RESULT_IO_ERROR -> new IOException(
- appSearchResult.getErrorMessage());
- case AppSearchResult.RESULT_SECURITY_ERROR -> new SecurityException(
- appSearchResult.getErrorMessage());
+ case AppSearchResult.RESULT_INVALID_ARGUMENT ->
+ new IllegalArgumentException(appSearchResult.getErrorMessage());
+ case AppSearchResult.RESULT_IO_ERROR ->
+ new IOException(appSearchResult.getErrorMessage());
+ case AppSearchResult.RESULT_SECURITY_ERROR ->
+ new SecurityException(appSearchResult.getErrorMessage());
default -> new IllegalStateException(appSearchResult.getErrorMessage());
};
}
diff --git a/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java b/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java
index fdd12b0..c4bfae9 100644
--- a/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java
+++ b/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java
@@ -56,16 +56,12 @@
super(genericDocument);
}
- /**
- * Returns a per-app runtime metadata schema name, to store all functions for that package.
- */
+ /** Returns a per-app runtime metadata schema name, to store all functions for that package. */
public static String getRuntimeSchemaNameForPackage(@NonNull String pkg) {
return RUNTIME_SCHEMA_TYPE + RUNTIME_SCHEMA_TYPE_SEPARATOR + Objects.requireNonNull(pkg);
}
- /**
- * Returns the document id for an app function's runtime metadata.
- */
+ /** Returns the document id for an app function's runtime metadata. */
public static String getDocumentIdForAppFunction(
@NonNull String pkg, @NonNull String functionId) {
return pkg + "/" + functionId;
@@ -74,15 +70,34 @@
/**
* Different packages have different visibility requirements. To allow for different visibility,
* we need to have per-package app function schemas.
+ *
* <p>This schema should be set visible to callers from the package owner itself and for callers
- * with {@link android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or {@link
- * android.permission.EXECUTE_APP_FUNCTIONS} permissions.
+ * with {@link android.Manifest.permission#EXECUTE_APP_FUNCTIONS} or {@link
+ * android.Manifest.permission#EXECUTE_APP_FUNCTIONS_TRUSTED} permissions.
*
* @param packageName The package name to create a schema for.
*/
@NonNull
public static AppSearchSchema createAppFunctionRuntimeSchema(@NonNull String packageName) {
- return new AppSearchSchema.Builder(getRuntimeSchemaNameForPackage(packageName))
+ return getAppFunctionRuntimeSchemaBuilder(getRuntimeSchemaNameForPackage(packageName))
+ .addParentType(RUNTIME_SCHEMA_TYPE)
+ .build();
+ }
+
+ /**
+ * Creates a parent schema for all app function runtime schemas.
+ *
+ * <p>This schema should be set visible to the owner itself and for callers with {@link
+ * android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or {@link
+ * android.permission.EXECUTE_APP_FUNCTIONS} permissions.
+ */
+ public static AppSearchSchema createParentAppFunctionRuntimeSchema() {
+ return getAppFunctionRuntimeSchemaBuilder(RUNTIME_SCHEMA_TYPE).build();
+ }
+
+ private static AppSearchSchema.Builder getAppFunctionRuntimeSchemaBuilder(
+ @NonNull String schemaType) {
+ return new AppSearchSchema.Builder(schemaType)
.addProperty(
new AppSearchSchema.StringPropertyConfig.Builder(PROPERTY_FUNCTION_ID)
.setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
@@ -109,27 +124,21 @@
.build())
.addProperty(
new AppSearchSchema.StringPropertyConfig.Builder(
- PROPERTY_APP_FUNCTION_STATIC_METADATA_QUALIFIED_ID)
+ PROPERTY_APP_FUNCTION_STATIC_METADATA_QUALIFIED_ID)
.setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
.setJoinableValueType(
AppSearchSchema.StringPropertyConfig
.JOINABLE_VALUE_TYPE_QUALIFIED_ID)
- .build())
- .addParentType(RUNTIME_SCHEMA_TYPE)
- .build();
+ .build());
}
- /**
- * Returns the function id. This might look like "com.example.message#send_message".
- */
+ /** Returns the function id. This might look like "com.example.message#send_message". */
@NonNull
public String getFunctionId() {
return Objects.requireNonNull(getPropertyString(PROPERTY_FUNCTION_ID));
}
- /**
- * Returns the package name of the package that owns this function.
- */
+ /** Returns the package name of the package that owns this function. */
@NonNull
public String getPackageName() {
return Objects.requireNonNull(getPropertyString(PROPERTY_PACKAGE_NAME));
@@ -144,9 +153,7 @@
return (Boolean) getProperty(PROPERTY_ENABLED);
}
- /**
- * Returns the qualified id linking to the static metadata of the app function.
- */
+ /** Returns the qualified id linking to the static metadata of the app function. */
@Nullable
@VisibleForTesting
public String getAppFunctionStaticMetadataQualifiedId() {
@@ -157,10 +164,10 @@
/**
* Creates a Builder for a {@link AppFunctionRuntimeMetadata}.
*
- * @param packageName the name of the package that owns the function.
- * @param functionId the id of the function.
+ * @param packageName the name of the package that owns the function.
+ * @param functionId the id of the function.
* @param staticMetadataQualifiedId the qualified static metadata id that this runtime
- * metadata refers to.
+ * metadata refers to.
*/
public Builder(
@NonNull String packageName,
@@ -177,11 +184,9 @@
// Set qualified id automatically
setPropertyString(
- PROPERTY_APP_FUNCTION_STATIC_METADATA_QUALIFIED_ID,
- staticMetadataQualifiedId);
+ PROPERTY_APP_FUNCTION_STATIC_METADATA_QUALIFIED_ID, staticMetadataQualifiedId);
}
-
/**
* Sets an indicator specifying if the function is enabled or not. This would override the
* default enabled state in the static metadata ({@link
@@ -193,9 +198,7 @@
return this;
}
- /**
- * Creates the {@link AppFunctionRuntimeMetadata} GenericDocument.
- */
+ /** Creates the {@link AppFunctionRuntimeMetadata} GenericDocument. */
@NonNull
public AppFunctionRuntimeMetadata build() {
return new AppFunctionRuntimeMetadata(super.build());
diff --git a/core/java/android/app/appfunctions/AppFunctionService.java b/core/java/android/app/appfunctions/AppFunctionService.java
index 22bc908..c27141a 100644
--- a/core/java/android/app/appfunctions/AppFunctionService.java
+++ b/core/java/android/app/appfunctions/AppFunctionService.java
@@ -58,8 +58,7 @@
* applications can not abuse it.
*/
@NonNull
- public static final String SERVICE_INTERFACE =
- "android.app.appfunctions.AppFunctionService";
+ public static final String SERVICE_INTERFACE = "android.app.appfunctions.AppFunctionService";
private final Binder mBinder =
new IAppFunctionService.Stub() {
@@ -67,23 +66,20 @@
public void executeAppFunction(
@NonNull ExecuteAppFunctionRequest request,
@NonNull IExecuteAppFunctionCallback callback) {
- if (AppFunctionService.this.checkCallingPermission(
- BIND_APP_FUNCTION_SERVICE) == PERMISSION_DENIED) {
+ if (AppFunctionService.this.checkCallingPermission(BIND_APP_FUNCTION_SERVICE)
+ == PERMISSION_DENIED) {
throw new SecurityException("Can only be called by the system server.");
}
SafeOneTimeExecuteAppFunctionCallback safeCallback =
new SafeOneTimeExecuteAppFunctionCallback(callback);
try {
- AppFunctionService.this.onExecuteFunction(
- request,
- safeCallback::onResult);
+ AppFunctionService.this.onExecuteFunction(request, safeCallback::onResult);
} catch (Exception ex) {
// Apps should handle exceptions. But if they don't, report the error on
// behalf of them.
safeCallback.onResult(
ExecuteAppFunctionResponse.newFailure(
- getResultCode(ex),
- ex.getMessage(), /*extras=*/ null));
+ getResultCode(ex), ex.getMessage(), /* extras= */ null));
}
}
};
@@ -111,7 +107,7 @@
* thread and dispatch the result with the given callback. You should always report back the
* result using the callback, no matter if the execution was successful or not.
*
- * @param request The function execution request.
+ * @param request The function execution request.
* @param callback A callback to report back the result.
*/
@MainThread
diff --git a/core/java/android/app/appfunctions/AppFunctionStaticMetadataHelper.java b/core/java/android/app/appfunctions/AppFunctionStaticMetadataHelper.java
index 6d4172a..926cc9a 100644
--- a/core/java/android/app/appfunctions/AppFunctionStaticMetadataHelper.java
+++ b/core/java/android/app/appfunctions/AppFunctionStaticMetadataHelper.java
@@ -27,9 +27,9 @@
/**
* Contains constants and helper related to static metadata represented with {@code
* com.android.server.appsearch.appsindexer.appsearchtypes.AppFunctionStaticMetadata}.
- * <p>
- * The constants listed here **must not change** and be kept consistent with the canonical
- * static metadata class.
+ *
+ * <p>The constants listed here **must not change** and be kept consistent with the canonical static
+ * metadata class.
*
* @hide
*/
@@ -45,9 +45,7 @@
public static final String APP_FUNCTION_STATIC_METADATA_DB = "apps-db";
public static final String APP_FUNCTION_INDEXER_PACKAGE = "android";
- /**
- * Returns a per-app static metadata schema name, to store all functions for that package.
- */
+ /** Returns a per-app static metadata schema name, to store all functions for that package. */
public static String getStaticSchemaNameForPackage(@NonNull String pkg) {
return STATIC_SCHEMA_TYPE + "-" + Objects.requireNonNull(pkg);
}
@@ -59,8 +57,8 @@
}
/**
- * Returns the fully qualified Id used in AppSearch for the given package and function id
- * app function static metadata.
+ * Returns the fully qualified Id used in AppSearch for the given package and function id app
+ * function static metadata.
*/
public static String getStaticMetadataQualifiedId(String packageName, String functionId) {
return DocumentIdUtil.createQualifiedId(
diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.java b/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.java
index 2f3c555..e623fa1 100644
--- a/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.java
+++ b/core/java/android/app/appfunctions/ExecuteAppFunctionAidlRequest.java
@@ -23,7 +23,6 @@
import android.os.Parcelable;
import android.os.UserHandle;
-
import java.util.Objects;
/**
@@ -40,8 +39,7 @@
public ExecuteAppFunctionAidlRequest createFromParcel(Parcel in) {
ExecuteAppFunctionRequest clientRequest =
ExecuteAppFunctionRequest.CREATOR.createFromParcel(in);
- UserHandle userHandle =
- UserHandle.CREATOR.createFromParcel(in);
+ UserHandle userHandle = UserHandle.CREATOR.createFromParcel(in);
String callingPackage = in.readString8();
return new ExecuteAppFunctionAidlRequest(
clientRequest, userHandle, callingPackage);
@@ -53,19 +51,13 @@
}
};
- /**
- * The client request to execute an app function.
- */
+ /** The client request to execute an app function. */
private final ExecuteAppFunctionRequest mClientRequest;
- /**
- * The user handle of the user to execute the app function.
- */
+ /** The user handle of the user to execute the app function. */
private final UserHandle mUserHandle;
- /**
- * The package name of the app that is requesting to execute the app function.
- */
+ /** The package name of the app that is requesting to execute the app function. */
private final String mCallingPackage;
public ExecuteAppFunctionAidlRequest(
@@ -87,25 +79,19 @@
dest.writeString8(mCallingPackage);
}
- /**
- * Returns the client request to execute an app function.
- */
+ /** Returns the client request to execute an app function. */
@NonNull
public ExecuteAppFunctionRequest getClientRequest() {
return mClientRequest;
}
- /**
- * Returns the user handle of the user to execute the app function.
- */
+ /** Returns the user handle of the user to execute the app function. */
@NonNull
public UserHandle getUserHandle() {
return mUserHandle;
}
- /**
- * Returns the package name of the app that is requesting to execute the app function.
- */
+ /** Returns the package name of the app that is requesting to execute the app function. */
@NonNull
public String getCallingPackage() {
return mCallingPackage;
diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionRequest.java b/core/java/android/app/appfunctions/ExecuteAppFunctionRequest.java
index db3de62..fe7fd88 100644
--- a/core/java/android/app/appfunctions/ExecuteAppFunctionRequest.java
+++ b/core/java/android/app/appfunctions/ExecuteAppFunctionRequest.java
@@ -16,7 +16,6 @@
package android.app.appfunctions;
-
import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER;
import android.annotation.FlaggedApi;
@@ -28,9 +27,7 @@
import java.util.Objects;
-/**
- * A request to execute an app function.
- */
+/** A request to execute an app function. */
@FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER)
public final class ExecuteAppFunctionRequest implements Parcelable {
@NonNull
@@ -40,8 +37,8 @@
public ExecuteAppFunctionRequest createFromParcel(Parcel parcel) {
String targetPackageName = parcel.readString8();
String functionIdentifier = parcel.readString8();
- GenericDocumentWrapper parameters = GenericDocumentWrapper
- .CREATOR.createFromParcel(parcel);
+ GenericDocumentWrapper parameters =
+ GenericDocumentWrapper.CREATOR.createFromParcel(parcel);
Bundle extras = parcel.readBundle(Bundle.class.getClassLoader());
return new ExecuteAppFunctionRequest(
targetPackageName, functionIdentifier, extras, parameters);
@@ -52,34 +49,30 @@
return new ExecuteAppFunctionRequest[size];
}
};
+
+ /** Returns the package name of the app that hosts the function. */
+ @NonNull private final String mTargetPackageName;
+
/**
- * Returns the package name of the app that hosts the function.
+ * Returns the unique string identifier of the app function to be executed. TODO(b/357551503):
+ * Document how callers can get the available function identifiers.
*/
- @NonNull
- private final String mTargetPackageName;
+ @NonNull private final String mFunctionIdentifier;
+
+ /** Returns additional metadata relevant to this function execution request. */
+ @NonNull private final Bundle mExtras;
+
/**
- * Returns the unique string identifier of the app function to be executed.
- * TODO(b/357551503): Document how callers can get the available function identifiers.
- */
- @NonNull
- private final String mFunctionIdentifier;
- /**
- * Returns additional metadata relevant to this function execution request.
- */
- @NonNull
- private final Bundle mExtras;
- /**
- * Returns the parameters required to invoke this function. Within this [GenericDocument],
- * the property names are the names of the function parameters and the property values are the
+ * Returns the parameters required to invoke this function. Within this [GenericDocument], the
+ * property names are the names of the function parameters and the property values are the
* values of those parameters.
*
* <p>The document may have missing parameters. Developers are advised to implement defensive
* handling measures.
- * <p>
- * TODO(b/357551503): Document how function parameters can be obtained for function execution
+ *
+ * <p>TODO(b/357551503): Document how function parameters can be obtained for function execution
*/
- @NonNull
- private final GenericDocumentWrapper mParameters;
+ @NonNull private final GenericDocumentWrapper mParameters;
private ExecuteAppFunctionRequest(
@NonNull String targetPackageName,
@@ -92,17 +85,13 @@
mParameters = Objects.requireNonNull(parameters);
}
- /**
- * Returns the package name of the app that hosts the function.
- */
+ /** Returns the package name of the app that hosts the function. */
@NonNull
public String getTargetPackageName() {
return mTargetPackageName;
}
- /**
- * Returns the unique string identifier of the app function to be executed.
- */
+ /** Returns the unique string identifier of the app function to be executed. */
@NonNull
public String getFunctionIdentifier() {
return mFunctionIdentifier;
@@ -111,8 +100,8 @@
/**
* Returns the function parameters. The key is the parameter name, and the value is the
* parameter value.
- * <p>
- * The bundle may have missing parameters. Developers are advised to implement defensive
+ *
+ * <p>The bundle may have missing parameters. Developers are advised to implement defensive
* handling measures.
*/
@NonNull
@@ -120,9 +109,7 @@
return mParameters.getValue();
}
- /**
- * Returns the additional data relevant to this function execution.
- */
+ /** Returns the additional data relevant to this function execution. */
@NonNull
public Bundle getExtras() {
return mExtras;
@@ -141,37 +128,28 @@
return 0;
}
- /**
- * Builder for {@link ExecuteAppFunctionRequest}.
- */
+ /** Builder for {@link ExecuteAppFunctionRequest}. */
public static final class Builder {
+ @NonNull private final String mTargetPackageName;
+ @NonNull private final String mFunctionIdentifier;
+ @NonNull private Bundle mExtras = Bundle.EMPTY;
+
@NonNull
- private final String mTargetPackageName;
- @NonNull
- private final String mFunctionIdentifier;
- @NonNull
- private Bundle mExtras = Bundle.EMPTY;
- @NonNull
- private GenericDocument mParameters =
- new GenericDocument.Builder<>("", "", "").build();
+ private GenericDocument mParameters = new GenericDocument.Builder<>("", "", "").build();
public Builder(@NonNull String targetPackageName, @NonNull String functionIdentifier) {
mTargetPackageName = Objects.requireNonNull(targetPackageName);
mFunctionIdentifier = Objects.requireNonNull(functionIdentifier);
}
- /**
- * Sets the additional data relevant to this function execution.
- */
+ /** Sets the additional data relevant to this function execution. */
@NonNull
public Builder setExtras(@NonNull Bundle extras) {
mExtras = Objects.requireNonNull(extras);
return this;
}
- /**
- * Sets the function parameters.
- */
+ /** Sets the function parameters. */
@NonNull
public Builder setParameters(@NonNull GenericDocument parameters) {
Objects.requireNonNull(parameters);
@@ -179,13 +157,13 @@
return this;
}
- /**
- * Builds the {@link ExecuteAppFunctionRequest}.
- */
+ /** Builds the {@link ExecuteAppFunctionRequest}. */
@NonNull
public ExecuteAppFunctionRequest build() {
return new ExecuteAppFunctionRequest(
- mTargetPackageName, mFunctionIdentifier, mExtras,
+ mTargetPackageName,
+ mFunctionIdentifier,
+ mExtras,
new GenericDocumentWrapper(mParameters));
}
}
diff --git a/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java
index 58d4088..f6580e6 100644
--- a/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java
+++ b/core/java/android/app/appfunctions/ExecuteAppFunctionResponse.java
@@ -31,9 +31,7 @@
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
-/**
- * The response to an app function execution.
- */
+/** The response to an app function execution. */
@FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER)
public final class ExecuteAppFunctionResponse implements Parcelable {
@NonNull
@@ -43,10 +41,10 @@
public ExecuteAppFunctionResponse createFromParcel(Parcel parcel) {
GenericDocumentWrapper resultWrapper =
Objects.requireNonNull(
- GenericDocumentWrapper
- .CREATOR.createFromParcel(parcel));
- Bundle extras = Objects.requireNonNull(
- parcel.readBundle(Bundle.class.getClassLoader()));
+ GenericDocumentWrapper.CREATOR.createFromParcel(parcel));
+ Bundle extras =
+ Objects.requireNonNull(
+ parcel.readBundle(Bundle.class.getClassLoader()));
int resultCode = parcel.readInt();
String errorMessage = parcel.readString8();
return new ExecuteAppFunctionResponse(
@@ -58,14 +56,15 @@
return new ExecuteAppFunctionResponse[size];
}
};
+
/**
- * The name of the property that stores the function return value within the
- * {@code resultDocument}.
+ * The name of the property that stores the function return value within the {@code
+ * resultDocument}.
*
* <p>See {@link GenericDocument#getProperty(String)} for more information.
*
- * <p>If the function returns {@code void} or throws an error, the {@code resultDocument}
- * will be empty {@link GenericDocument}.
+ * <p>If the function returns {@code void} or throws an error, the {@code resultDocument} will
+ * be empty {@link GenericDocument}.
*
* <p>If the {@code resultDocument} is empty, {@link GenericDocument#getProperty(String)} will
* return {@code null}.
@@ -74,19 +73,13 @@
*/
public static final String PROPERTY_RETURN_VALUE = "returnValue";
- /**
- * The call was successful.
- */
+ /** The call was successful. */
public static final int RESULT_OK = 0;
- /**
- * The caller does not have the permission to execute an app function.
- */
+ /** The caller does not have the permission to execute an app function. */
public static final int RESULT_DENIED = 1;
- /**
- * An unknown error occurred while processing the call in the AppFunctionService.
- */
+ /** An unknown error occurred while processing the call in the AppFunctionService. */
public static final int RESULT_APP_UNKNOWN_ERROR = 2;
/**
@@ -103,45 +96,36 @@
*/
public static final int RESULT_INVALID_ARGUMENT = 4;
- /**
- * The operation was timed out.
- */
+ /** The operation was timed out. */
public static final int RESULT_TIMED_OUT = 5;
- /**
- * The result code of the app function execution.
- */
- @ResultCode
- private final int mResultCode;
+ /** The result code of the app function execution. */
+ @ResultCode private final int mResultCode;
/**
* The error message associated with the result, if any. This is {@code null} if the result code
* is {@link #RESULT_OK}.
*/
- @Nullable
- private final String mErrorMessage;
+ @Nullable private final String mErrorMessage;
/**
* Returns the return value of the executed function.
*
- * <p>The return value is stored in a {@link GenericDocument} with the key
- * {@link #PROPERTY_RETURN_VALUE}.
+ * <p>The return value is stored in a {@link GenericDocument} with the key {@link
+ * #PROPERTY_RETURN_VALUE}.
*
* <p>See {@link #getResultDocument} for more information on extracting the return value.
*/
- @NonNull
- private final GenericDocumentWrapper mResultDocumentWrapper;
+ @NonNull private final GenericDocumentWrapper mResultDocumentWrapper;
- /**
- * Returns the additional metadata data relevant to this function execution response.
- */
- @NonNull
- private final Bundle mExtras;
+ /** Returns the additional metadata data relevant to this function execution response. */
+ @NonNull private final Bundle mExtras;
- private ExecuteAppFunctionResponse(@NonNull GenericDocumentWrapper resultDocumentWrapper,
- @NonNull Bundle extras,
- @ResultCode int resultCode,
- @Nullable String errorMessage) {
+ private ExecuteAppFunctionResponse(
+ @NonNull GenericDocumentWrapper resultDocumentWrapper,
+ @NonNull Bundle extras,
+ @ResultCode int resultCode,
+ @Nullable String errorMessage) {
mResultDocumentWrapper = Objects.requireNonNull(resultDocumentWrapper);
mExtras = Objects.requireNonNull(extras);
mResultCode = resultCode;
@@ -165,42 +149,38 @@
* Returns a successful response.
*
* @param resultDocument The return value of the executed function.
- * @param extras The additional metadata data relevant to this function execution
- * response.
+ * @param extras The additional metadata data relevant to this function execution response.
*/
@NonNull
@FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER)
- public static ExecuteAppFunctionResponse newSuccess(@NonNull GenericDocument resultDocument,
- @Nullable Bundle extras) {
+ public static ExecuteAppFunctionResponse newSuccess(
+ @NonNull GenericDocument resultDocument, @Nullable Bundle extras) {
Objects.requireNonNull(resultDocument);
Bundle actualExtras = getActualExtras(extras);
GenericDocumentWrapper resultDocumentWrapper = new GenericDocumentWrapper(resultDocument);
return new ExecuteAppFunctionResponse(
- resultDocumentWrapper, actualExtras, RESULT_OK, /*errorMessage=*/null);
+ resultDocumentWrapper, actualExtras, RESULT_OK, /* errorMessage= */ null);
}
/**
* Returns a failure response.
*
- * @param resultCode The result code of the app function execution.
- * @param extras The additional metadata data relevant to this function execution
- * response.
+ * @param resultCode The result code of the app function execution.
+ * @param extras The additional metadata data relevant to this function execution response.
* @param errorMessage The error message associated with the result, if any.
*/
@NonNull
@FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER)
- public static ExecuteAppFunctionResponse newFailure(@ResultCode int resultCode,
- @Nullable String errorMessage,
- @Nullable Bundle extras) {
+ public static ExecuteAppFunctionResponse newFailure(
+ @ResultCode int resultCode, @Nullable String errorMessage, @Nullable Bundle extras) {
if (resultCode == RESULT_OK) {
throw new IllegalArgumentException("resultCode must not be RESULT_OK");
}
Bundle actualExtras = getActualExtras(extras);
- GenericDocumentWrapper emptyWrapper = new GenericDocumentWrapper(
- new GenericDocument.Builder<>("", "", "").build());
- return new ExecuteAppFunctionResponse(
- emptyWrapper, actualExtras, resultCode, errorMessage);
+ GenericDocumentWrapper emptyWrapper =
+ new GenericDocumentWrapper(new GenericDocument.Builder<>("", "", "").build());
+ return new ExecuteAppFunctionResponse(emptyWrapper, actualExtras, resultCode, errorMessage);
}
private static Bundle getActualExtras(@Nullable Bundle extras) {
@@ -213,12 +193,13 @@
/**
* Returns a generic document containing the return value of the executed function.
*
- * <p>The {@link #PROPERTY_RETURN_VALUE} key can be used to obtain the return value.</p>
+ * <p>The {@link #PROPERTY_RETURN_VALUE} key can be used to obtain the return value.
*
* <p>An empty document is returned if {@link #isSuccess} is {@code false} or if the executed
* function does not produce a return value.
*
* <p>Sample code for extracting the return value:
+ *
* <pre>
* GenericDocument resultDocument = response.getResultDocument();
* Object returnValue = resultDocument.getProperty(PROPERTY_RETURN_VALUE);
@@ -234,17 +215,15 @@
return mResultDocumentWrapper.getValue();
}
- /**
- * Returns the extras of the app function execution.
- */
+ /** Returns the extras of the app function execution. */
@NonNull
public Bundle getExtras() {
return mExtras;
}
/**
- * Returns {@code true} if {@link #getResultCode} equals
- * {@link ExecuteAppFunctionResponse#RESULT_OK}.
+ * Returns {@code true} if {@link #getResultCode} equals {@link
+ * ExecuteAppFunctionResponse#RESULT_OK}.
*/
public boolean isSuccess() {
return getResultCode() == RESULT_OK;
@@ -289,14 +268,13 @@
@IntDef(
prefix = {"RESULT_"},
value = {
- RESULT_OK,
- RESULT_DENIED,
- RESULT_APP_UNKNOWN_ERROR,
- RESULT_INTERNAL_ERROR,
- RESULT_INVALID_ARGUMENT,
- RESULT_TIMED_OUT,
+ RESULT_OK,
+ RESULT_DENIED,
+ RESULT_APP_UNKNOWN_ERROR,
+ RESULT_INTERNAL_ERROR,
+ RESULT_INVALID_ARGUMENT,
+ RESULT_TIMED_OUT,
})
@Retention(RetentionPolicy.SOURCE)
- public @interface ResultCode {
- }
+ public @interface ResultCode {}
}
diff --git a/core/java/android/app/appfunctions/GenericDocumentWrapper.java b/core/java/android/app/appfunctions/GenericDocumentWrapper.java
index 8c76c8e..84b1837 100644
--- a/core/java/android/app/appfunctions/GenericDocumentWrapper.java
+++ b/core/java/android/app/appfunctions/GenericDocumentWrapper.java
@@ -56,16 +56,13 @@
return new GenericDocumentWrapper[size];
}
};
- @NonNull
- private final GenericDocument mGenericDocument;
+ @NonNull private final GenericDocument mGenericDocument;
public GenericDocumentWrapper(@NonNull GenericDocument genericDocument) {
mGenericDocument = Objects.requireNonNull(genericDocument);
}
- /**
- * Returns the wrapped {@link android.app.appsearch.GenericDocument}
- */
+ /** Returns the wrapped {@link android.app.appsearch.GenericDocument} */
@NonNull
public GenericDocument getValue() {
return mGenericDocument;
@@ -86,6 +83,5 @@
} finally {
parcel.recycle();
}
-
}
}
diff --git a/core/java/android/app/jank/OWNERS b/core/java/android/app/jank/OWNERS
new file mode 100644
index 0000000..806de57
--- /dev/null
+++ b/core/java/android/app/jank/OWNERS
@@ -0,0 +1,4 @@
+steventerrell@google.com
+carmenjackson@google.com
+jjaggi@google.com
+pmuetschard@google.com
\ No newline at end of file
diff --git a/core/java/android/app/notification.aconfig b/core/java/android/app/notification.aconfig
index 606ca33..9891e89 100644
--- a/core/java/android/app/notification.aconfig
+++ b/core/java/android/app/notification.aconfig
@@ -128,6 +128,16 @@
}
flag {
+ name: "notif_channel_crop_vibration_effects"
+ namespace: "systemui"
+ description: "Limits the size of vibration effects that can be stored in a NotificationChannel"
+ bug: "345881518"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "evenly_divided_call_style_action_layout"
namespace: "systemui"
description: "Evenly divides horizontal space for action buttons in CallStyle notifications."
diff --git a/core/java/android/appwidget/flags.aconfig b/core/java/android/appwidget/flags.aconfig
index 4e0379e..7117f25 100644
--- a/core/java/android/appwidget/flags.aconfig
+++ b/core/java/android/appwidget/flags.aconfig
@@ -57,3 +57,10 @@
description: "Enable support for persisting RemoteViews previews to Protobuf"
bug: "306546610"
}
+
+flag {
+ name: "remote_document_support"
+ namespace: "app_widgets"
+ description: "Remote document support features in Q2 2025 release"
+ bug: "339721781"
+}
\ No newline at end of file
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index cf34452..473ab27 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -1259,6 +1259,8 @@
/**
* Called when a window with a secure surface is shown on the device.
*
+ * <p>Note that this is called only when the window is associated with an activity.</p>
+ *
* @param displayId The display ID on which the window was shown.
* @param componentName The component name of the activity that showed the window.
* @param user The user associated with the activity.
diff --git a/core/java/android/companion/virtual/flags/flags.aconfig b/core/java/android/companion/virtual/flags/flags.aconfig
index 22a9ccf..748260b 100644
--- a/core/java/android/companion/virtual/flags/flags.aconfig
+++ b/core/java/android/companion/virtual/flags/flags.aconfig
@@ -98,11 +98,11 @@
}
flag {
- name: "camera_multiple_input_streams"
- is_exported: true
- namespace: "virtual_devices"
- description: "Expose multiple surface for the virtual camera owner for different stream resolution"
- bug: "341083465"
+ name: "camera_multiple_input_streams"
+ is_exported: true
+ namespace: "virtual_devices"
+ description: "Expose multiple surface for the virtual camera owner for different stream resolution"
+ bug: "341083465"
}
flag {
@@ -111,3 +111,18 @@
description: "Device awareness in power and display APIs"
bug: "285020111"
}
+
+flag {
+ namespace: "virtual_devices"
+ name: "display_power_manager_apis"
+ description: "Make relevant PowerManager APIs display aware by default"
+ bug: "365042486"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "status_bar_and_insets"
+ namespace: "virtual_devices"
+ description: "Allow for status bar and insets on virtual devices"
+ bug: "350007866"
+}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 3bf0f032..12c5d07 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -33,6 +33,7 @@
import android.annotation.Nullable;
import android.annotation.PermissionMethod;
import android.annotation.PermissionName;
+import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.StringDef;
import android.annotation.StringRes;
@@ -6678,6 +6679,8 @@
* Use with {@link #getSystemService(String)} to retrieve a {@link
* android.webkit.WebViewUpdateManager} for accessing the WebView update service.
*
+ * <p>This can only be used on devices with {@link PackageManager#FEATURE_WEBVIEW}.
+ *
* @see #getSystemService(String)
* @see android.webkit.WebViewUpdateManager
* @hide
@@ -6685,6 +6688,7 @@
@FlaggedApi(android.webkit.Flags.FLAG_UPDATE_SERVICE_IPC_WRAPPER)
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@SuppressLint("ServiceName")
+ @RequiresFeature(PackageManager.FEATURE_WEBVIEW)
public static final String WEBVIEW_UPDATE_SERVICE = "webviewupdate";
/**
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index abb0d8d..031380d 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -86,6 +86,7 @@
import android.util.proto.ProtoOutputStream;
import com.android.internal.util.XmlUtils;
+import com.android.modules.expresslog.Counter;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -7650,13 +7651,6 @@
| FLAG_GRANT_PREFIX_URI_PERMISSION;
/**
- * Flags that are not normally set by application code, but set for you by the system.
- */
- private static final int SYSTEM_ONLY_FLAGS = FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
- | FLAG_ACTIVITY_BROUGHT_TO_FRONT
- | FLAG_RECEIVER_FROM_SHELL;
-
- /**
* Local flag indicating this instance was created by copy constructor.
*/
private static final int LOCAL_FLAG_FROM_COPY = 1 << 0;
@@ -7709,11 +7703,6 @@
@TestApi
public static final int EXTENDED_FLAG_FILTER_MISMATCH = 1 << 0;
- /**
- * Extended flags that are not normally set by application code, but set for you by the system.
- */
- private static final int SYSTEM_ONLY_EXTENDED_FLAGS = EXTENDED_FLAG_FILTER_MISMATCH;
-
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// toUri() and parseUri() options.
@@ -12657,28 +12646,6 @@
}
}
- /**
- * Prepare this {@link Intent} to enter system_server.
- *
- * @hide
- */
- public void prepareToEnterSystemServer() {
- // Refuse possible leaked file descriptors
- if (hasFileDescriptors()) {
- throw new IllegalArgumentException("File descriptors passed in Intent");
- }
- // These flags are set only by the system, and should be stripped out as soon as the intent
- // is received by system_server from the caller so it can be properly updated later.
- removeFlags(SYSTEM_ONLY_FLAGS);
- removeExtendedFlags(SYSTEM_ONLY_EXTENDED_FLAGS);
- if (mOriginalIntent != null) {
- mOriginalIntent.prepareToEnterSystemServer();
- }
- if (mSelector != null) {
- mSelector.prepareToEnterSystemServer();
- }
- }
-
/** @hide */
public boolean hasWebURI() {
if (getData() == null) {
@@ -12839,6 +12806,8 @@
new ClipData.Item(text, htmlText, null, stream));
setClipData(clipData);
if (stream != null) {
+ logCounterIfFlagsMissing(FLAG_GRANT_READ_URI_PERMISSION,
+ "intents.value_explicit_uri_grant_for_send_action");
addFlags(FLAG_GRANT_READ_URI_PERMISSION);
}
return true;
@@ -12880,6 +12849,8 @@
setClipData(clipData);
if (streams != null) {
+ logCounterIfFlagsMissing(FLAG_GRANT_READ_URI_PERMISSION,
+ "intents.value_explicit_uri_grant_for_send_multiple_action");
addFlags(FLAG_GRANT_READ_URI_PERMISSION);
}
return true;
@@ -12899,6 +12870,10 @@
putExtra(MediaStore.EXTRA_OUTPUT, output);
setClipData(ClipData.newRawUri("", output));
+
+ logCounterIfFlagsMissing(
+ FLAG_GRANT_WRITE_URI_PERMISSION | FLAG_GRANT_READ_URI_PERMISSION,
+ "intents.value_explicit_uri_grant_for_image_capture_action");
addFlags(FLAG_GRANT_WRITE_URI_PERMISSION|FLAG_GRANT_READ_URI_PERMISSION);
return true;
}
@@ -12907,6 +12882,12 @@
return false;
}
+ private void logCounterIfFlagsMissing(int requiredFlags, String metricId) {
+ if ((getFlags() & requiredFlags) != requiredFlags) {
+ Counter.logIncrement(metricId);
+ }
+ }
+
@android.ravenwood.annotation.RavenwoodThrow
private Uri maybeConvertFileToContentUri(Context context, Uri uri) {
if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 495ae60..34bea1a 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -849,6 +849,12 @@
*/
public static final int PRIVATE_FLAG_EXT_CPU_OVERRIDE = 1 << 5;
+ /**
+ * Whether the app has been previously not launched
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_EXT_NOT_LAUNCHED = 1 << 6;
+
/** @hide */
@IntDef(flag = true, prefix = { "PRIVATE_FLAG_EXT_" }, value = {
PRIVATE_FLAG_EXT_PROFILEABLE,
@@ -857,6 +863,7 @@
PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK,
PRIVATE_FLAG_EXT_ALLOWLISTED_FOR_HIDDEN_APIS,
PRIVATE_FLAG_EXT_CPU_OVERRIDE,
+ PRIVATE_FLAG_EXT_NOT_LAUNCHED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ApplicationInfoPrivateFlagsExt {}
@@ -2664,6 +2671,22 @@
}
/**
+ * Returns whether the app in the STOPPED state.
+ * @hide
+ */
+ public boolean isStopped() {
+ return (flags & ApplicationInfo.FLAG_STOPPED) != 0;
+ }
+
+ /**
+ * Returns whether the app was never launched (any process started) before.
+ * @hide
+ */
+ public boolean isNotLaunched() {
+ return (privateFlagsExt & ApplicationInfo.PRIVATE_FLAG_EXT_NOT_LAUNCHED) != 0;
+ }
+
+ /**
* Checks if a changeId is enabled for the current user
* @param changeId The changeId to verify
* @return True of the changeId is enabled
diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig
index 3a33ef9..9eec7a4 100644
--- a/core/java/android/content/pm/multiuser.aconfig
+++ b/core/java/android/content/pm/multiuser.aconfig
@@ -161,6 +161,16 @@
}
flag {
+ name: "fix_avatar_content_provider_null_authority"
+ namespace: "multiuser"
+ description: "Fix crash when content provider authority is null."
+ bug: "362880068"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "fix_avatar_picker_not_responding_for_new_user"
namespace: "multiuser"
description: "Avatar picker is not responding after selecting photo for new user."
@@ -416,4 +426,13 @@
metadata {
purpose: PURPOSE_BUGFIX
}
-}
\ No newline at end of file
+}
+
+
+flag {
+ name: "caching_development_improvements"
+ namespace: "multiuser"
+ description: "System API to simplify caching implamentations"
+ bug: "364947162"
+ is_fixed_read_only: true
+}
diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java
index 6514872..ef59e0a 100644
--- a/core/java/android/database/CursorWindow.java
+++ b/core/java/android/database/CursorWindow.java
@@ -26,6 +26,10 @@
import android.database.sqlite.SQLiteException;
import android.os.Parcel;
import android.os.Parcelable;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
+import android.ravenwood.annotation.RavenwoodThrow;
import dalvik.annotation.optimization.FastNative;
import dalvik.system.CloseGuard;
@@ -40,9 +44,8 @@
* consumer for reading.
* </p>
*/
-@android.ravenwood.annotation.RavenwoodKeepWholeClass
-@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
- "com.android.platform.test.ravenwood.nativesubstitution.CursorWindow_host")
+@RavenwoodKeepWholeClass
+@RavenwoodRedirectionClass("CursorWindow_host")
public class CursorWindow extends SQLiteClosable implements Parcelable {
private static final String STATS_TAG = "CursorWindowStats";
@@ -63,48 +66,69 @@
private final CloseGuard mCloseGuard;
// May throw CursorWindowAllocationException
+ @RavenwoodRedirect
private static native long nativeCreate(String name, int cursorWindowSize);
// May throw CursorWindowAllocationException
+ @RavenwoodRedirect
private static native long nativeCreateFromParcel(Parcel parcel);
+ @RavenwoodRedirect
private static native void nativeDispose(long windowPtr);
+ @RavenwoodRedirect
private static native void nativeWriteToParcel(long windowPtr, Parcel parcel);
+ @RavenwoodRedirect
private static native String nativeGetName(long windowPtr);
+ @RavenwoodRedirect
private static native byte[] nativeGetBlob(long windowPtr, int row, int column);
+ @RavenwoodRedirect
private static native String nativeGetString(long windowPtr, int row, int column);
+ @RavenwoodThrow
private static native void nativeCopyStringToBuffer(long windowPtr, int row, int column,
CharArrayBuffer buffer);
+ @RavenwoodRedirect
private static native boolean nativePutBlob(long windowPtr, byte[] value, int row, int column);
+ @RavenwoodRedirect
private static native boolean nativePutString(long windowPtr, String value,
int row, int column);
// Below native methods don't do unconstrained work, so are FastNative for performance
@FastNative
+ @RavenwoodThrow
private static native void nativeClear(long windowPtr);
@FastNative
+ @RavenwoodRedirect
private static native int nativeGetNumRows(long windowPtr);
@FastNative
+ @RavenwoodRedirect
private static native boolean nativeSetNumColumns(long windowPtr, int columnNum);
@FastNative
+ @RavenwoodRedirect
private static native boolean nativeAllocRow(long windowPtr);
@FastNative
+ @RavenwoodThrow
private static native void nativeFreeLastRow(long windowPtr);
@FastNative
+ @RavenwoodRedirect
private static native int nativeGetType(long windowPtr, int row, int column);
@FastNative
+ @RavenwoodRedirect
private static native long nativeGetLong(long windowPtr, int row, int column);
@FastNative
+ @RavenwoodRedirect
private static native double nativeGetDouble(long windowPtr, int row, int column);
@FastNative
+ @RavenwoodRedirect
private static native boolean nativePutLong(long windowPtr, long value, int row, int column);
@FastNative
+ @RavenwoodRedirect
private static native boolean nativePutDouble(long windowPtr, double value, int row, int column);
@FastNative
+ @RavenwoodThrow
private static native boolean nativePutNull(long windowPtr, int row, int column);
diff --git a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
index fc72db3..6682b36 100644
--- a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
@@ -61,7 +61,6 @@
BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL,
BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED,
BIOMETRIC_ERROR_RE_ENROLL,
- BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED,
FINGERPRINT_ERROR_UNKNOWN,
FINGERPRINT_ERROR_BAD_CALIBRATION,
BIOMETRIC_ERROR_POWER_PRESSED})
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index fbed50a..ac72116 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1537,9 +1537,14 @@
* be made, and for firing pre-capture flash pulses to estimate
* scene brightness and required final capture flash power, when
* the flash is enabled.</p>
- * <p>Normally, this entry should be set to START for only a
- * single request, and the application should wait until the
- * sequence completes before starting a new one.</p>
+ * <p>Flash is enabled during precapture sequence when:</p>
+ * <ul>
+ * <li>AE mode is ON_ALWAYS_FLASH</li>
+ * <li>AE mode is ON_AUTO_FLASH and the scene is deemed too dark without flash, or</li>
+ * <li>AE mode is ON and flash mode is TORCH or SINGLE</li>
+ * </ul>
+ * <p>Normally, this entry should be set to START for only single request, and the
+ * application should wait until the sequence completes before starting a new one.</p>
* <p>When a precapture metering sequence is finished, the camera device
* may lock the auto-exposure routine internally to be able to accurately expose the
* subsequent still capture image (<code>{@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent} == STILL_CAPTURE</code>).
@@ -2705,6 +2710,13 @@
* in {@link CameraCharacteristics#FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL android.flash.singleStrengthDefaultLevel}.
* If {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is set to any of <code>ON_AUTO_FLASH</code>, <code>ON_ALWAYS_FLASH</code>,
* <code>ON_AUTO_FLASH_REDEYE</code>, <code>ON_EXTERNAL_FLASH</code> values, then the strengthLevel will be ignored.</p>
+ * <p>When AE mode is ON and flash mode is TORCH or SINGLE, the application should make sure
+ * the AE mode, flash mode, and flash strength level remain the same between precapture
+ * trigger request and final capture request. The flash strength level being set during
+ * precapture sequence is used by the camera device as a reference. The actual strength
+ * may be less, and the auto-exposure routine makes sure proper conversions of sensor
+ * exposure time and sensitivities between precapture and final capture for the specified
+ * strength level.</p>
* <p><b>Range of valid values:</b><br>
* <code>[1-{@link CameraCharacteristics#FLASH_TORCH_STRENGTH_MAX_LEVEL android.flash.torchStrengthMaxLevel}]</code> when the {@link CaptureRequest#FLASH_MODE android.flash.mode} is
* set to TORCH;
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index d652b4c..34ce92c 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -935,9 +935,14 @@
* be made, and for firing pre-capture flash pulses to estimate
* scene brightness and required final capture flash power, when
* the flash is enabled.</p>
- * <p>Normally, this entry should be set to START for only a
- * single request, and the application should wait until the
- * sequence completes before starting a new one.</p>
+ * <p>Flash is enabled during precapture sequence when:</p>
+ * <ul>
+ * <li>AE mode is ON_ALWAYS_FLASH</li>
+ * <li>AE mode is ON_AUTO_FLASH and the scene is deemed too dark without flash, or</li>
+ * <li>AE mode is ON and flash mode is TORCH or SINGLE</li>
+ * </ul>
+ * <p>Normally, this entry should be set to START for only single request, and the
+ * application should wait until the sequence completes before starting a new one.</p>
* <p>When a precapture metering sequence is finished, the camera device
* may lock the auto-exposure routine internally to be able to accurately expose the
* subsequent still capture image (<code>{@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent} == STILL_CAPTURE</code>).
@@ -2821,8 +2826,6 @@
* boost when the light level threshold is exceeded.</p>
* <p>This state indicates when low light boost is 'ACTIVE' and applied. Similarly, it can
* indicate when it is not being applied by returning 'INACTIVE'.</p>
- * <p>This key will be absent from the CaptureResult if AE mode is not set to
- * 'ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY.</p>
* <p>The default value will always be 'INACTIVE'.</p>
* <p><b>Possible values:</b></p>
* <ul>
@@ -2996,6 +2999,13 @@
* in {@link CameraCharacteristics#FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL android.flash.singleStrengthDefaultLevel}.
* If {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is set to any of <code>ON_AUTO_FLASH</code>, <code>ON_ALWAYS_FLASH</code>,
* <code>ON_AUTO_FLASH_REDEYE</code>, <code>ON_EXTERNAL_FLASH</code> values, then the strengthLevel will be ignored.</p>
+ * <p>When AE mode is ON and flash mode is TORCH or SINGLE, the application should make sure
+ * the AE mode, flash mode, and flash strength level remain the same between precapture
+ * trigger request and final capture request. The flash strength level being set during
+ * precapture sequence is used by the camera device as a reference. The actual strength
+ * may be less, and the auto-exposure routine makes sure proper conversions of sensor
+ * exposure time and sensitivities between precapture and final capture for the specified
+ * strength level.</p>
* <p><b>Range of valid values:</b><br>
* <code>[1-{@link CameraCharacteristics#FLASH_TORCH_STRENGTH_MAX_LEVEL android.flash.torchStrengthMaxLevel}]</code> when the {@link CaptureRequest#FLASH_MODE android.flash.mode} is
* set to TORCH;
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index a60c48e..c7dba6c 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -80,6 +80,7 @@
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -90,6 +91,17 @@
private final String TAG;
private final boolean DEBUG = false;
+ private static final ThreadFactory sThreadFactory = new ThreadFactory() {
+ private static final ThreadFactory mFactory = Executors.defaultThreadFactory();
+
+ @Override
+ public Thread newThread(Runnable r) {
+ Thread thread = mFactory.newThread(r);
+ thread.setName("CameraDeviceExecutor");
+ return thread;
+ }
+ };
+
private static final int REQUEST_ID_NONE = -1;
/**
@@ -354,7 +366,11 @@
mCameraId = cameraId;
if (Flags.singleThreadExecutor()) {
mDeviceCallback = new ClientStateCallback(executor, callback);
- mDeviceExecutor = Executors.newSingleThreadExecutor();
+ if (Flags.singleThreadExecutorNaming()) {
+ mDeviceExecutor = Executors.newSingleThreadExecutor(sThreadFactory);
+ } else {
+ mDeviceExecutor = Executors.newSingleThreadExecutor();
+ }
} else {
mDeviceCallback = callback;
mDeviceExecutor = executor;
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 83f2685..2d96bba 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -241,12 +241,12 @@
KeyGlyphMap getKeyGlyphMap(int deviceId);
- @EnforcePermission("MANAGE_KEY_GESTURES")
+ @PermissionManuallyEnforced
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
+ "android.Manifest.permission.MANAGE_KEY_GESTURES)")
void registerKeyGestureEventListener(IKeyGestureEventListener listener);
- @EnforcePermission("MANAGE_KEY_GESTURES")
+ @PermissionManuallyEnforced
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
+ "android.Manifest.permission.MANAGE_KEY_GESTURES)")
void unregisterKeyGestureEventListener(IKeyGestureEventListener listener);
diff --git a/core/java/android/hardware/input/input_framework.aconfig b/core/java/android/hardware/input/input_framework.aconfig
index 077bd82..fcd6c31 100644
--- a/core/java/android/hardware/input/input_framework.aconfig
+++ b/core/java/android/hardware/input/input_framework.aconfig
@@ -101,8 +101,19 @@
}
flag {
+ namespace: "input_native"
+ name: "manage_key_gestures"
+ description: "Manage key gestures through Input APIs"
+ is_exported: true
+ bug: "358569822"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "keyboard_repeat_keys"
- namespace: "input"
+ namespace: "input_native"
description: "Allow configurable timeout before key repeat and repeat delay rate for key repeats"
bug: "336585002"
}
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 3a58993..218b023 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -256,6 +256,10 @@
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
public int[] getContextHubHandles() {
+ if (Flags.removeOldContextHubApis()) {
+ return null;
+ }
+
try {
return mService.getContextHubHandles();
} catch (RemoteException e) {
@@ -277,6 +281,10 @@
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
public ContextHubInfo getContextHubInfo(int hubHandle) {
+ if (Flags.removeOldContextHubApis()) {
+ return null;
+ }
+
try {
return mService.getContextHubInfo(hubHandle);
} catch (RemoteException e) {
@@ -308,6 +316,10 @@
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
public int loadNanoApp(int hubHandle, @NonNull NanoApp app) {
+ if (Flags.removeOldContextHubApis()) {
+ return -1;
+ }
+
try {
return mService.loadNanoApp(hubHandle, app);
} catch (RemoteException e) {
@@ -335,6 +347,10 @@
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
public int unloadNanoApp(int nanoAppHandle) {
+ if (Flags.removeOldContextHubApis()) {
+ return -1;
+ }
+
try {
return mService.unloadNanoApp(nanoAppHandle);
} catch (RemoteException e) {
@@ -375,6 +391,10 @@
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
@Nullable public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) {
+ if (Flags.removeOldContextHubApis()) {
+ return null;
+ }
+
try {
return mService.getNanoAppInstanceInfo(nanoAppHandle);
} catch (RemoteException e) {
@@ -398,6 +418,10 @@
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
@NonNull public int[] findNanoAppOnHub(int hubHandle, @NonNull NanoAppFilter filter) {
+ if (Flags.removeOldContextHubApis()) {
+ return null;
+ }
+
try {
return mService.findNanoAppOnHub(hubHandle, filter);
} catch (RemoteException e) {
@@ -433,6 +457,10 @@
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
public int sendMessage(int hubHandle, int nanoAppHandle, @NonNull ContextHubMessage message) {
+ if (Flags.removeOldContextHubApis()) {
+ return -1;
+ }
+
try {
return mService.sendMessage(hubHandle, nanoAppHandle, message);
} catch (RemoteException e) {
@@ -648,6 +676,10 @@
@Deprecated
@SuppressLint("RequiresPermission")
public int registerCallback(@NonNull Callback callback) {
+ if (Flags.removeOldContextHubApis()) {
+ return -1;
+ }
+
return registerCallback(callback, null);
}
@@ -657,6 +689,10 @@
*/
@Deprecated
public int registerCallback(ICallback callback) {
+ if (Flags.removeOldContextHubApis()) {
+ return -1;
+ }
+
if (mLocalCallback != null) {
Log.w(TAG, "Max number of local callbacks reached!");
return -1;
@@ -682,6 +718,10 @@
@Deprecated
@SuppressLint("RequiresPermission")
public int registerCallback(Callback callback, Handler handler) {
+ if (Flags.removeOldContextHubApis()) {
+ return -1;
+ }
+
synchronized(this) {
if (mCallback != null) {
Log.w(TAG, "Max number of callbacks reached!");
@@ -1041,16 +1081,20 @@
@SuppressLint("RequiresPermission")
@Deprecated
public int unregisterCallback(@NonNull Callback callback) {
- synchronized(this) {
- if (callback != mCallback) {
- Log.w(TAG, "Cannot recognize callback!");
- return -1;
- }
+ if (Flags.removeOldContextHubApis()) {
+ return -1;
+ }
- mCallback = null;
- mCallbackHandler = null;
- }
- return 0;
+ synchronized (this) {
+ if (callback != mCallback) {
+ Log.w(TAG, "Cannot recognize callback!");
+ return -1;
+ }
+
+ mCallback = null;
+ mCallbackHandler = null;
+ }
+ return 0;
}
/**
@@ -1059,6 +1103,10 @@
*/
@Deprecated
public synchronized int unregisterCallback(ICallback callback) {
+ if (Flags.removeOldContextHubApis()) {
+ return -1;
+ }
+
if (callback != mLocalCallback) {
Log.w(TAG, "Cannot recognize local callback!");
return -1;
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index ff737a4..49e2358 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -664,9 +664,14 @@
int mStatusIcon;
+ /** Latest reported value of back disposition mode. */
@BackDispositionMode
int mBackDisposition;
+ /** Latest reported value of IME window visibility state. */
+ @ImeWindowVisibility
+ private int mImeWindowVisibility;
+
private Object mLock = new Object();
@GuardedBy("mLock")
private boolean mNotifyUserActionSent;
@@ -1047,7 +1052,7 @@
ImeTracker.forLogging().onFailed(statsToken,
ImeTracker.PHASE_IME_ON_SHOW_SOFT_INPUT_TRUE);
}
- setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition);
+ setImeWindowVisibility(computeImeWindowVis());
final boolean isVisible = isInputViewShown();
final boolean visibilityChanged = isVisible != wasVisible;
@@ -1357,9 +1362,22 @@
mImeSurfaceRemoverRunnable = null;
}
- private void setImeWindowStatus(@ImeWindowVisibility int visibilityFlags,
+ /**
+ * Sets the IME window visibility state.
+ *
+ * @param vis the IME window visibility state to be set.
+ */
+ private void setImeWindowVisibility(@ImeWindowVisibility int vis) {
+ if (vis == mImeWindowVisibility) {
+ return;
+ }
+ mImeWindowVisibility = vis;
+ setImeWindowStatus(mImeWindowVisibility, mBackDisposition);
+ }
+
+ private void setImeWindowStatus(@ImeWindowVisibility int vis,
@BackDispositionMode int backDisposition) {
- mPrivOps.setImeWindowStatusAsync(visibilityFlags, backDisposition);
+ mPrivOps.setImeWindowStatusAsync(vis, backDisposition);
}
/** Set region of the keyboard to be avoided from back gesture */
@@ -1986,7 +2004,7 @@
}
// If user uses hard keyboard, IME button should always be shown.
boolean showing = onEvaluateInputViewShown();
- setImeWindowStatus(IME_ACTIVE | (showing ? IME_VISIBLE : 0), mBackDisposition);
+ setImeWindowVisibility(IME_ACTIVE | (showing ? IME_VISIBLE : 0));
}
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@@ -2053,7 +2071,7 @@
return;
}
mBackDisposition = disposition;
- setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition);
+ setImeWindowStatus(mImeWindowVisibility, mBackDisposition);
}
/**
@@ -3132,14 +3150,8 @@
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.showWindow");
mDecorViewWasVisible = mDecorViewVisible;
mInShowWindow = true;
- final int previousImeWindowStatus =
- (mDecorViewVisible ? IME_ACTIVE : 0) | (isInputViewShown()
- ? (!mWindowVisible ? -1 : IME_VISIBLE) : 0);
startViews(prepareWindow(showInput));
- final int nextImeWindowStatus = mapToImeWindowStatus();
- if (previousImeWindowStatus != nextImeWindowStatus) {
- setImeWindowStatus(nextImeWindowStatus, mBackDisposition);
- }
+ setImeWindowVisibility(computeImeWindowVis());
mNavigationBarController.onWindowShown();
// compute visibility
@@ -3317,7 +3329,7 @@
ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_IME_HIDE_WINDOW);
ImeTracing.getInstance().triggerServiceDump("InputMethodService#hideWindow", mDumper,
null /* icProto */);
- setImeWindowStatus(0 /* visibilityFlags */, mBackDisposition);
+ setImeWindowVisibility(0 /* vis */);
if (android.view.inputmethod.Flags.refactorInsetsController()) {
// The ImeInsetsSourceProvider need the statsToken when dispatching the control. We
// send the token here, so that another request in the provider can be cancelled.
@@ -4492,10 +4504,10 @@
};
}
+ /** Computes the IME window visibility state. */
@ImeWindowVisibility
- private int mapToImeWindowStatus() {
- return IME_ACTIVE
- | (isInputViewShown() ? IME_VISIBLE : 0);
+ private int computeImeWindowVis() {
+ return IME_ACTIVE | (isInputViewShown() ? IME_VISIBLE : 0);
}
/**
diff --git a/core/java/android/os/AppZygote.java b/core/java/android/os/AppZygote.java
index 07fbe4a..0541a96 100644
--- a/core/java/android/os/AppZygote.java
+++ b/core/java/android/os/AppZygote.java
@@ -111,12 +111,15 @@
try {
int runtimeFlags = Zygote.getMemorySafetyRuntimeFlagsForSecondaryZygote(
mAppInfo, mProcessInfo);
+
+ final int[] sharedAppGid = {
+ UserHandle.getSharedAppGid(UserHandle.getAppId(mAppInfo.uid)) };
mZygote = Process.ZYGOTE_PROCESS.startChildZygote(
"com.android.internal.os.AppZygoteInit",
mAppInfo.processName + "_zygote",
mZygoteUid,
mZygoteUid,
- null, // gids
+ sharedAppGid, // Zygote gets access to shared app GID for profiles
runtimeFlags,
"app_zygote", // seInfo
abi, // abi
diff --git a/core/java/android/os/ArtModuleServiceManager.java b/core/java/android/os/ArtModuleServiceManager.java
index e0b631d..995094b 100644
--- a/core/java/android/os/ArtModuleServiceManager.java
+++ b/core/java/android/os/ArtModuleServiceManager.java
@@ -37,10 +37,12 @@
/** A class that exposes the method to obtain each system service. */
public static final class ServiceRegisterer {
@NonNull private final String mServiceName;
+ private final boolean mRetry;
/** @hide */
- public ServiceRegisterer(@NonNull String serviceName) {
+ public ServiceRegisterer(@NonNull String serviceName, boolean retry) {
mServiceName = serviceName;
+ mRetry = retry;
}
/**
@@ -53,27 +55,47 @@
*/
@Nullable
public IBinder waitForService() {
- return ServiceManager.waitForService(mServiceName);
+ if (mRetry) {
+ return ServiceManager.waitForService(mServiceName);
+ }
+ IBinder binder = ServiceManager.getService(mServiceName);
+ for (int remainingTimeMs = 5000; binder == null && remainingTimeMs > 0;
+ remainingTimeMs -= 100) {
+ // There can be a race:
+ // 1. Client A invokes "ctl.start", which starts the service.
+ // 2. Client A gets a service handle from `ServiceManager.getService`.
+ // 3. Client B invokes "ctl.start", which does nothing because the service is
+ // already running.
+ // 4. Client A drops the service handle. The service is notified that there is no
+ // more client at that point, so it shuts down itself.
+ // 5. Client B cannot get a service handle from `ServiceManager.getService` because
+ // the service is shut down.
+ // To address this problem, we invoke "ctl.start" repeatedly.
+ SystemProperties.set("ctl.start", mServiceName);
+ SystemClock.sleep(100);
+ binder = ServiceManager.getService(mServiceName);
+ }
+ return binder;
}
}
/** Returns {@link ServiceRegisterer} for the "artd" service. */
@NonNull
public ServiceRegisterer getArtdServiceRegisterer() {
- return new ServiceRegisterer("artd");
+ return new ServiceRegisterer("artd", true /* retry */);
}
/** Returns {@link ServiceRegisterer} for the "artd_pre_reboot" service. */
@NonNull
@FlaggedApi(Flags.FLAG_USE_ART_SERVICE_V2)
public ServiceRegisterer getArtdPreRebootServiceRegisterer() {
- return new ServiceRegisterer("artd_pre_reboot");
+ return new ServiceRegisterer("artd_pre_reboot", false /* retry */);
}
/** Returns {@link ServiceRegisterer} for the "dexopt_chroot_setup" service. */
@NonNull
@FlaggedApi(Flags.FLAG_USE_ART_SERVICE_V2)
public ServiceRegisterer getDexoptChrootSetupServiceRegisterer() {
- return new ServiceRegisterer("dexopt_chroot_setup");
+ return new ServiceRegisterer("dexopt_chroot_setup", true /* retry */);
}
}
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
index 1100731..c22f46c 100644
--- a/core/java/android/os/BinderProxy.java
+++ b/core/java/android/os/BinderProxy.java
@@ -646,6 +646,37 @@
private native boolean unlinkToDeathNative(DeathRecipient recipient, int flags);
/**
+ * This list is to hold strong reference to the frozen state callbacks. The callbacks are only
+ * weakly referenced by JNI so the strong references here are needed to keep the callbacks
+ * around until the proxy is GC'ed.
+ */
+ private List<IFrozenStateChangeCallback> mFrozenStateChangeCallbacks =
+ Collections.synchronizedList(new ArrayList<>());
+
+ /**
+ * See {@link IBinder#addFrozenStateChangeCallback(IFrozenStateChangeCallback)}
+ */
+ public void addFrozenStateChangeCallback(IFrozenStateChangeCallback callback)
+ throws RemoteException {
+ addFrozenStateChangeCallbackNative(callback);
+ mFrozenStateChangeCallbacks.add(callback);
+ }
+
+ /**
+ * See {@link IBinder#removeFrozenStateChangeCallback}
+ */
+ public boolean removeFrozenStateChangeCallback(IFrozenStateChangeCallback callback) {
+ mFrozenStateChangeCallbacks.remove(callback);
+ return removeFrozenStateChangeCallbackNative(callback);
+ }
+
+ private native void addFrozenStateChangeCallbackNative(IFrozenStateChangeCallback callback)
+ throws RemoteException;
+
+ private native boolean removeFrozenStateChangeCallbackNative(
+ IFrozenStateChangeCallback callback);
+
+ /**
* Perform a dump on the remote object
*
* @param fd The raw file descriptor that the dump is being sent to.
@@ -730,6 +761,17 @@
}
}
+ private static void invokeFrozenStateChangeCallback(
+ IFrozenStateChangeCallback callback, IBinder binderProxy, int stateIndex) {
+ try {
+ callback.onFrozenStateChanged(binderProxy,
+ IFrozenStateChangeCallback.State.values()[stateIndex]);
+ } catch (RuntimeException exc) {
+ Log.w("BinderNative", "Uncaught exception from frozen state change callback",
+ exc);
+ }
+ }
+
/**
* C++ pointer to BinderProxyNativeData. That consists of strong pointers to the
* native IBinder object, and a DeathRecipientList.
diff --git a/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java b/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
index da2eec9..b2d9260 100644
--- a/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
+++ b/core/java/android/os/ConcurrentMessageQueue/MessageQueue.java
@@ -19,9 +19,9 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.TestApi;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Trace;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
import android.util.Log;
import android.util.Printer;
import android.util.SparseArray;
@@ -51,9 +51,8 @@
* <p>You can retrieve the MessageQueue for the current thread with
* {@link Looper#myQueue() Looper.myQueue()}.
*/
-@android.ravenwood.annotation.RavenwoodKeepWholeClass
-@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
- "com.android.platform.test.ravenwood.nativesubstitution.MessageQueue_host")
+@RavenwoodKeepWholeClass
+@RavenwoodRedirectionClass("MessageQueue_host")
public final class MessageQueue {
private static final String TAG = "ConcurrentMessageQueue";
private static final boolean DEBUG = false;
@@ -345,11 +344,17 @@
// Barriers are indicated by messages with a null target whose arg1 field carries the token.
private final AtomicInteger mNextBarrierToken = new AtomicInteger(1);
+ @RavenwoodRedirect
private static native long nativeInit();
+ @RavenwoodRedirect
private static native void nativeDestroy(long ptr);
+ @RavenwoodRedirect
private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
+ @RavenwoodRedirect
private static native void nativeWake(long ptr);
+ @RavenwoodRedirect
private static native boolean nativeIsPolling(long ptr);
+ @RavenwoodRedirect
private static native void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
MessageQueue(boolean quitAllowed) {
diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java
index 50242ba..8185e8e 100644
--- a/core/java/android/os/IBinder.java
+++ b/core/java/android/os/IBinder.java
@@ -376,4 +376,53 @@
* return value instead.
*/
public boolean unlinkToDeath(@NonNull DeathRecipient recipient, int flags);
+
+ /** @hide */
+ interface IFrozenStateChangeCallback {
+ enum State {FROZEN, UNFROZEN};
+
+ /**
+ * Interface for receiving a callback when the process hosting an IBinder
+ * has changed its frozen state.
+ * @param who The IBinder whose hosting process has changed state.
+ * @param state The latest state.
+ */
+ void onFrozenStateChanged(@NonNull IBinder who, State state);
+ }
+
+ /**
+ * {@link addFrozenStateChangeCallback} provides a callback mechanism to notify about process
+ * frozen/unfrozen events. Upon registration and any subsequent state changes, the callback is
+ * invoked with the latest process frozen state.
+ *
+ * <p>If the listener process (the one using this API) is itself frozen, state change events
+ * might be combined into a single one with the latest frozen state. This single event would
+ * then be delivered when the listener process becomes unfrozen. Similarly, if an event happens
+ * before the previous event is consumed, they might be combined. This means the callback might
+ * not be called for every single state change, so don't rely on this API to count how many
+ * times the state has changed.</p>
+ *
+ * <p>The callback is automatically removed when all references to the binder proxy are
+ * dropped.</p>
+ *
+ * <p>You will only receive state change notifications for remote binders, as local binders by
+ * definition can't be frozen without you being frozen too.</p>
+ *
+ * <p>@throws {@link UnsupportedOperationException} if the kernel binder driver does not support
+ * this feature.
+ * @hide
+ */
+ default void addFrozenStateChangeCallback(@NonNull IFrozenStateChangeCallback callback)
+ throws RemoteException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Unregister a {@link IFrozenStateChangeCallback}. The callback will no longer be invoked when
+ * the hosting process changes its frozen state.
+ * @hide
+ */
+ default boolean removeFrozenStateChangeCallback(@NonNull IFrozenStateChangeCallback callback) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/core/java/android/os/LegacyMessageQueue/MessageQueue.java b/core/java/android/os/LegacyMessageQueue/MessageQueue.java
index 6b9b349..4474e7e 100644
--- a/core/java/android/os/LegacyMessageQueue/MessageQueue.java
+++ b/core/java/android/os/LegacyMessageQueue/MessageQueue.java
@@ -20,9 +20,9 @@
import android.annotation.NonNull;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Handler;
-import android.os.Process;
-import android.os.Trace;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
import android.util.Log;
import android.util.Printer;
import android.util.SparseArray;
@@ -42,9 +42,8 @@
* <p>You can retrieve the MessageQueue for the current thread with
* {@link Looper#myQueue() Looper.myQueue()}.
*/
-@android.ravenwood.annotation.RavenwoodKeepWholeClass
-@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
- "com.android.platform.test.ravenwood.nativesubstitution.MessageQueue_host")
+@RavenwoodKeepWholeClass
+@RavenwoodRedirectionClass("MessageQueue_host")
public final class MessageQueue {
private static final String TAG = "MessageQueue";
private static final boolean DEBUG = false;
@@ -79,12 +78,18 @@
@UnsupportedAppUsage
private int mNextBarrierToken;
+ @RavenwoodRedirect
private native static long nativeInit();
+ @RavenwoodRedirect
private native static void nativeDestroy(long ptr);
@UnsupportedAppUsage
+ @RavenwoodRedirect
private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
+ @RavenwoodRedirect
private native static void nativeWake(long ptr);
+ @RavenwoodRedirect
private native static boolean nativeIsPolling(long ptr);
+ @RavenwoodRedirect
private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
MessageQueue(boolean quitAllowed) {
diff --git a/core/java/android/os/LockedMessageQueue/MessageQueue.java b/core/java/android/os/LockedMessageQueue/MessageQueue.java
index b24e14b..f1affce 100644
--- a/core/java/android/os/LockedMessageQueue/MessageQueue.java
+++ b/core/java/android/os/LockedMessageQueue/MessageQueue.java
@@ -20,8 +20,9 @@
import android.annotation.NonNull;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Handler;
-import android.os.Trace;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
import android.util.Log;
import android.util.Printer;
import android.util.SparseArray;
@@ -44,9 +45,8 @@
* <p>You can retrieve the MessageQueue for the current thread with
* {@link Looper#myQueue() Looper.myQueue()}.
*/
-@android.ravenwood.annotation.RavenwoodKeepWholeClass
-@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
- "com.android.platform.test.ravenwood.nativesubstitution.MessageQueue_host")
+@RavenwoodKeepWholeClass
+@RavenwoodRedirectionClass("MessageQueue_host")
public final class MessageQueue {
private static final String TAG = "LockedMessageQueue";
private static final boolean DEBUG = false;
@@ -389,12 +389,18 @@
@UnsupportedAppUsage
private int mNextBarrierToken;
+ @RavenwoodRedirect
private native static long nativeInit();
+ @RavenwoodRedirect
private native static void nativeDestroy(long ptr);
@UnsupportedAppUsage
+ @RavenwoodRedirect
private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
+ @RavenwoodRedirect
private native static void nativeWake(long ptr);
+ @RavenwoodRedirect
private native static boolean nativeIsPolling(long ptr);
+ @RavenwoodRedirect
private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
MessageQueue(boolean quitAllowed) {
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 47096db..2ac2ae9 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -28,7 +28,8 @@
import android.app.AppOpsManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.ravenwood.annotation.RavenwoodKeepWholeClass;
-import android.ravenwood.annotation.RavenwoodNativeSubstitutionClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
import android.ravenwood.annotation.RavenwoodReplace;
import android.ravenwood.annotation.RavenwoodThrow;
import android.text.TextUtils;
@@ -233,8 +234,7 @@
* {@link #readSparseArray(ClassLoader, Class)}.
*/
@RavenwoodKeepWholeClass
-@RavenwoodNativeSubstitutionClass(
- "com.android.platform.test.ravenwood.nativesubstitution.Parcel_host")
+@RavenwoodRedirectionClass("Parcel_host")
public final class Parcel {
private static final boolean DEBUG_RECYCLE = false;
@@ -387,6 +387,7 @@
private static final int SIZE_COMPLEX_TYPE = 1;
@CriticalNative
+ @RavenwoodRedirect
private static native void nativeMarkSensitive(long nativePtr);
@FastNative
@RavenwoodThrow
@@ -395,86 +396,126 @@
@RavenwoodThrow
private static native boolean nativeIsForRpc(long nativePtr);
@CriticalNative
+ @RavenwoodRedirect
private static native int nativeDataSize(long nativePtr);
@CriticalNative
+ @RavenwoodRedirect
private static native int nativeDataAvail(long nativePtr);
@CriticalNative
+ @RavenwoodRedirect
private static native int nativeDataPosition(long nativePtr);
@CriticalNative
+ @RavenwoodRedirect
private static native int nativeDataCapacity(long nativePtr);
@FastNative
+ @RavenwoodRedirect
private static native void nativeSetDataSize(long nativePtr, int size);
@CriticalNative
+ @RavenwoodRedirect
private static native void nativeSetDataPosition(long nativePtr, int pos);
@FastNative
+ @RavenwoodRedirect
private static native void nativeSetDataCapacity(long nativePtr, int size);
@CriticalNative
+ @RavenwoodRedirect
private static native boolean nativePushAllowFds(long nativePtr, boolean allowFds);
@CriticalNative
+ @RavenwoodRedirect
private static native void nativeRestoreAllowFds(long nativePtr, boolean lastValue);
+ @RavenwoodRedirect
private static native void nativeWriteByteArray(long nativePtr, byte[] b, int offset, int len);
+ @RavenwoodRedirect
private static native void nativeWriteBlob(long nativePtr, byte[] b, int offset, int len);
@CriticalNative
+ @RavenwoodRedirect
private static native int nativeWriteInt(long nativePtr, int val);
@CriticalNative
+ @RavenwoodRedirect
private static native int nativeWriteLong(long nativePtr, long val);
@CriticalNative
+ @RavenwoodRedirect
private static native int nativeWriteFloat(long nativePtr, float val);
@CriticalNative
+ @RavenwoodRedirect
private static native int nativeWriteDouble(long nativePtr, double val);
@RavenwoodThrow
private static native void nativeSignalExceptionForError(int error);
@FastNative
+ @RavenwoodRedirect
private static native void nativeWriteString8(long nativePtr, String val);
@FastNative
+ @RavenwoodRedirect
private static native void nativeWriteString16(long nativePtr, String val);
@FastNative
@RavenwoodThrow
private static native void nativeWriteStrongBinder(long nativePtr, IBinder val);
@FastNative
+ @RavenwoodRedirect
private static native void nativeWriteFileDescriptor(long nativePtr, FileDescriptor val);
+ @RavenwoodRedirect
private static native byte[] nativeCreateByteArray(long nativePtr);
+ @RavenwoodRedirect
private static native boolean nativeReadByteArray(long nativePtr, byte[] dest, int destLen);
+ @RavenwoodRedirect
private static native byte[] nativeReadBlob(long nativePtr);
@CriticalNative
+ @RavenwoodRedirect
private static native int nativeReadInt(long nativePtr);
@CriticalNative
+ @RavenwoodRedirect
private static native long nativeReadLong(long nativePtr);
@CriticalNative
+ @RavenwoodRedirect
private static native float nativeReadFloat(long nativePtr);
@CriticalNative
+ @RavenwoodRedirect
private static native double nativeReadDouble(long nativePtr);
@FastNative
+ @RavenwoodRedirect
private static native String nativeReadString8(long nativePtr);
@FastNative
+ @RavenwoodRedirect
private static native String nativeReadString16(long nativePtr);
@FastNative
@RavenwoodThrow
private static native IBinder nativeReadStrongBinder(long nativePtr);
@FastNative
+ @RavenwoodRedirect
private static native FileDescriptor nativeReadFileDescriptor(long nativePtr);
+ @RavenwoodRedirect
private static native long nativeCreate();
+ @RavenwoodRedirect
private static native void nativeFreeBuffer(long nativePtr);
+ @RavenwoodRedirect
private static native void nativeDestroy(long nativePtr);
+ @RavenwoodRedirect
private static native byte[] nativeMarshall(long nativePtr);
+ @RavenwoodRedirect
private static native void nativeUnmarshall(
long nativePtr, byte[] data, int offset, int length);
+ @RavenwoodRedirect
private static native int nativeCompareData(long thisNativePtr, long otherNativePtr);
+ @RavenwoodRedirect
private static native boolean nativeCompareDataInRange(
long ptrA, int offsetA, long ptrB, int offsetB, int length);
+ @RavenwoodRedirect
private static native void nativeAppendFrom(
long thisNativePtr, long otherNativePtr, int offset, int length);
@CriticalNative
+ @RavenwoodRedirect
private static native boolean nativeHasFileDescriptors(long nativePtr);
+ @RavenwoodRedirect
private static native boolean nativeHasFileDescriptorsInRange(
long nativePtr, int offset, int length);
+ @RavenwoodRedirect
private static native boolean nativeHasBinders(long nativePtr);
+ @RavenwoodRedirect
private static native boolean nativeHasBindersInRange(
long nativePtr, int offset, int length);
@RavenwoodThrow
diff --git a/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java b/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
index 79f229a..80c24a9 100644
--- a/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
+++ b/core/java/android/os/SemiConcurrentMessageQueue/MessageQueue.java
@@ -19,8 +19,9 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.TestApi;
-import android.os.Handler;
-import android.os.Trace;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
import android.util.Log;
import android.util.Printer;
import android.util.SparseArray;
@@ -37,8 +38,6 @@
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.PriorityQueue;
-import java.util.PriorityQueue;
-import java.util.PriorityQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
@@ -50,9 +49,8 @@
* <p>You can retrieve the MessageQueue for the current thread with
* {@link Looper#myQueue() Looper.myQueue()}.
*/
-@android.ravenwood.annotation.RavenwoodKeepWholeClass
-@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
- "com.android.platform.test.ravenwood.nativesubstitution.MessageQueue_host")
+@RavenwoodKeepWholeClass
+@RavenwoodRedirectionClass("MessageQueue_host")
public final class MessageQueue {
private static final String TAG = "SemiConcurrentMessageQueue";
private static final boolean DEBUG = false;
@@ -338,11 +336,17 @@
// Barriers are indicated by messages with a null target whose arg1 field carries the token.
private final AtomicInteger mNextBarrierToken = new AtomicInteger(1);
+ @RavenwoodRedirect
private static native long nativeInit();
+ @RavenwoodRedirect
private static native void nativeDestroy(long ptr);
+ @RavenwoodRedirect
private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
+ @RavenwoodRedirect
private static native void nativeWake(long ptr);
+ @RavenwoodRedirect
private static native boolean nativeIsPolling(long ptr);
+ @RavenwoodRedirect
private static native void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
MessageQueue(boolean quitAllowed) {
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index 0a38691..e53873b 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -21,11 +21,13 @@
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.ravenwood.annotation.RavenwoodKeepWholeClass;
-import android.ravenwood.annotation.RavenwoodNativeSubstitutionClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
import android.util.Log;
import android.util.MutableInt;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.ravenwood.RavenwoodEnvironment;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
@@ -56,8 +58,7 @@
*/
@SystemApi
@RavenwoodKeepWholeClass
-@RavenwoodNativeSubstitutionClass(
- "com.android.platform.test.ravenwood.nativesubstitution.SystemProperties_host")
+@RavenwoodRedirectionClass("SystemProperties_host")
public class SystemProperties {
private static final String TAG = "SystemProperties";
private static final boolean TRACK_KEY_ACCESS = false;
@@ -75,7 +76,7 @@
@UnsupportedAppUsage
@GuardedBy("sChangeCallbacks")
- private static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>();
+ static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>();
@GuardedBy("sRoReads")
private static final HashMap<String, MutableInt> sRoReads =
@@ -102,30 +103,18 @@
}
/** @hide */
+ @RavenwoodRedirect
public static void init$ravenwood(Map<String, String> values,
Predicate<String> keyReadablePredicate, Predicate<String> keyWritablePredicate) {
- native_init$ravenwood(values, keyReadablePredicate, keyWritablePredicate,
- SystemProperties::callChangeCallbacks);
- synchronized (sChangeCallbacks) {
- sChangeCallbacks.clear();
- }
+ throw RavenwoodEnvironment.notSupportedOnDevice();
}
/** @hide */
+ @RavenwoodRedirect
public static void reset$ravenwood() {
- native_reset$ravenwood();
- synchronized (sChangeCallbacks) {
- sChangeCallbacks.clear();
- }
+ throw RavenwoodEnvironment.notSupportedOnDevice();
}
- // These native methods are currently only implemented by Ravenwood, as it's the only
- // mechanism we have to jump to our RavenwoodNativeSubstitutionClass
- private static native void native_init$ravenwood(Map<String, String> values,
- Predicate<String> keyReadablePredicate, Predicate<String> keyWritablePredicate,
- Runnable changeCallback);
- private static native void native_reset$ravenwood();
-
// The one-argument version of native_get used to be a regular native function. Nowadays,
// we use the two-argument form of native_get all the time, but we can't just delete the
// one-argument overload: apps use it via reflection, as the UnsupportedAppUsage annotation
@@ -137,34 +126,46 @@
@FastNative
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @RavenwoodRedirect
private static native String native_get(String key, String def);
@FastNative
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @RavenwoodRedirect
private static native int native_get_int(String key, int def);
@FastNative
@UnsupportedAppUsage
+ @RavenwoodRedirect
private static native long native_get_long(String key, long def);
@FastNative
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @RavenwoodRedirect
private static native boolean native_get_boolean(String key, boolean def);
@FastNative
+ @RavenwoodRedirect
private static native long native_find(String name);
@FastNative
+ @RavenwoodRedirect
private static native String native_get(long handle);
@CriticalNative
+ @RavenwoodRedirect
private static native int native_get_int(long handle, int def);
@CriticalNative
+ @RavenwoodRedirect
private static native long native_get_long(long handle, long def);
@CriticalNative
+ @RavenwoodRedirect
private static native boolean native_get_boolean(long handle, boolean def);
// _NOT_ FastNative: native_set performs IPC and can block
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @RavenwoodRedirect
private static native void native_set(String key, String def);
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @RavenwoodRedirect
private static native void native_add_change_callback();
+ @RavenwoodRedirect
private static native void native_report_sysprop_change();
/**
@@ -300,7 +301,7 @@
}
@SuppressWarnings("unused") // Called from native code.
- private static void callChangeCallbacks() {
+ static void callChangeCallbacks() {
ArrayList<Runnable> callbacks = null;
synchronized (sChangeCallbacks) {
//Log.i("foo", "Calling " + sChangeCallbacks.size() + " change callbacks!");
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index f02d4a9..64a2dbc 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -540,6 +540,17 @@
/** @hide */
public abstract void validate();
+
+ /**
+ * If supported, truncate the length of this vibration effect to the provided length and return
+ * the result. Will always return null for repeating effects.
+ *
+ * @return The desired effect, or {@code null} if truncation is not applicable.
+ * @hide
+ */
+ @Nullable
+ public abstract VibrationEffect cropToLengthOrNull(int length);
+
/**
* Gets the estimated duration of the vibration in milliseconds.
*
@@ -866,6 +877,30 @@
}
}
+ /** @hide */
+ @Override
+ @Nullable
+ public VibrationEffect cropToLengthOrNull(int length) {
+ // drop repeating effects
+ if (mRepeatIndex >= 0) {
+ return null;
+ }
+
+ int segmentCount = mSegments.size();
+ if (segmentCount <= length) {
+ return this;
+ }
+
+ ArrayList truncated = new ArrayList(mSegments.subList(0, length));
+ Composed updated = new Composed(truncated, mRepeatIndex);
+ try {
+ updated.validate();
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ return updated;
+ }
+
@Override
public long getDuration() {
if (mRepeatIndex >= 0) {
@@ -1150,6 +1185,13 @@
"Vendor effect bundle must be non-empty");
}
+ /** @hide */
+ @Override
+ @Nullable
+ public VibrationEffect cropToLengthOrNull(int length) {
+ return null;
+ }
+
@Override
public long getDuration() {
return -1; // UNKNOWN
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 98904fe..0a05f70 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5150,13 +5150,19 @@
public static final String SCREEN_OFF_TIMEOUT = "screen_off_timeout";
/**
- * The screen backlight brightness between 0 and 255.
+ * The screen backlight brightness between 1 (minimum) and 255 (maximum).
+ *
+ * Use {@link android.view.WindowManager.LayoutParams#screenBrightness} to set the screen
+ * brightness instead.
*/
@Readable
public static final String SCREEN_BRIGHTNESS = "screen_brightness";
/**
- * Control whether to enable automatic brightness mode.
+ * Controls whether to enable automatic brightness mode. Value can be set to
+ * {@link #SCREEN_BRIGHTNESS_MODE_MANUAL} or {@link #SCREEN_BRIGHTNESS_MODE_AUTOMATIC}.
+ * If {@link #SCREEN_BRIGHTNESS_MODE_AUTOMATIC} is set, the system may change
+ * {@link #SCREEN_BRIGHTNESS} automatically.
*/
@Readable
public static final String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode";
diff --git a/core/java/android/service/chooser/flags.aconfig b/core/java/android/service/chooser/flags.aconfig
index 1f1a351..2b75493 100644
--- a/core/java/android/service/chooser/flags.aconfig
+++ b/core/java/android/service/chooser/flags.aconfig
@@ -2,6 +2,22 @@
container: "system"
flag {
+ name: "chooser_album_text"
+ is_exported: true
+ namespace: "intentresolver"
+ description: "Flag controlling the album text subtype hint for sharesheet"
+ bug: "323380224"
+}
+
+flag {
+ name: "enable_sharesheet_metadata_extra"
+ is_exported: true
+ namespace: "intentresolver"
+ description: "This flag enables sharesheet metadata to be displayed to users."
+ bug: "318942069"
+}
+
+flag {
name: "chooser_payload_toggling"
is_exported: true
namespace: "intentresolver"
diff --git a/core/java/android/service/notification/ZenPolicy.java b/core/java/android/service/notification/ZenPolicy.java
index 2669391..be0d7b3 100644
--- a/core/java/android/service/notification/ZenPolicy.java
+++ b/core/java/android/service/notification/ZenPolicy.java
@@ -393,6 +393,46 @@
}
/**
+ * Base Zen Policy used when {@link android.app.NotificationManager#setInterruptionFilter} is
+ * called with {@link android.app.NotificationManager#INTERRUPTION_FILTER_ALARMS} or an
+ * {@link android.app.AutomaticZenRule} specifies said filter.
+ *
+ * <p>Note that <em>visual effects</em> for filtered notifications are unset in this base
+ * policy, so should be merged on top of the default policy's visual effects (see
+ * {@link #overwrittenWith(ZenPolicy)}).
+ *
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_MODES_API)
+ public static ZenPolicy getBasePolicyInterruptionFilterAlarms() {
+ return new ZenPolicy.Builder()
+ .disallowAllSounds()
+ .allowAlarms(true)
+ .allowMedia(true)
+ .allowPriorityChannels(false)
+ .build();
+ }
+
+ /**
+ * Base Zen Policy used when {@link android.app.NotificationManager#setInterruptionFilter} is
+ * called with {@link android.app.NotificationManager#INTERRUPTION_FILTER_NONE} or an
+ * {@link android.app.AutomaticZenRule} specifies said filter.
+ *
+ * <p>Note that <em>visual effects</em> for filtered notifications are unset in this base
+ * policy, so it should be merged on top of the device default policy's visual effects (see
+ * {@link #overwrittenWith(ZenPolicy)}).
+ *
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_MODES_API)
+ public static ZenPolicy getBasePolicyInterruptionFilterNone() {
+ return new ZenPolicy.Builder()
+ .disallowAllSounds()
+ .allowPriorityChannels(false)
+ .build();
+ }
+
+ /**
* Conversation type that can bypass DND.
* @return {@link #CONVERSATION_SENDERS_UNSET}, {@link #CONVERSATION_SENDERS_ANYONE},
* {@link #CONVERSATION_SENDERS_IMPORTANT}, {@link #CONVERSATION_SENDERS_NONE}.
diff --git a/core/java/android/text/ClientFlags.java b/core/java/android/text/ClientFlags.java
index 5d84d17..bbe9cdb 100644
--- a/core/java/android/text/ClientFlags.java
+++ b/core/java/android/text/ClientFlags.java
@@ -35,20 +35,6 @@
}
/**
- * @see Flags#phraseStrictFallback()
- */
- public static boolean phraseStrictFallback() {
- return TextFlags.isFeatureEnabled(Flags.FLAG_PHRASE_STRICT_FALLBACK);
- }
-
- /**
- * @see Flags#useBoundsForWidth()
- */
- public static boolean useBoundsForWidth() {
- return TextFlags.isFeatureEnabled(Flags.FLAG_USE_BOUNDS_FOR_WIDTH);
- }
-
- /**
* @see Flags#fixLineHeightForLocale()
*/
public static boolean fixLineHeightForLocale() {
diff --git a/core/java/android/text/TextFlags.java b/core/java/android/text/TextFlags.java
index 9e02460..0f1b031 100644
--- a/core/java/android/text/TextFlags.java
+++ b/core/java/android/text/TextFlags.java
@@ -56,8 +56,6 @@
*/
public static final String[] TEXT_ACONFIGS_FLAGS = {
Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN,
- Flags.FLAG_PHRASE_STRICT_FALLBACK,
- Flags.FLAG_USE_BOUNDS_FOR_WIDTH,
Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE,
Flags.FLAG_ICU_BIDI_MIGRATION,
Flags.FLAG_FIX_MISALIGNED_CONTEXT_MENU,
@@ -70,8 +68,6 @@
*/
public static final boolean[] TEXT_ACONFIG_DEFAULT_VALUE = {
Flags.noBreakNoHyphenationSpan(),
- Flags.phraseStrictFallback(),
- Flags.useBoundsForWidth(),
Flags.fixLineHeightForLocale(),
Flags.icuBidiMigration(),
Flags.fixMisalignedContextMenu(),
diff --git a/core/java/android/text/flags/flags.aconfig b/core/java/android/text/flags/flags.aconfig
index d33c95e..b2be1a7 100644
--- a/core/java/android/text/flags/flags.aconfig
+++ b/core/java/android/text/flags/flags.aconfig
@@ -2,14 +2,6 @@
container: "system"
flag {
- name: "vendor_custom_locale_fallback"
- namespace: "text"
- description: "A feature flag that adds custom locale fallback to the vendor customization XML. This enables vendors to add their locale specific fonts, e.g. Japanese font."
- is_fixed_read_only: true
- bug: "278768958"
-}
-
-flag {
name: "new_fonts_fallback_xml"
is_exported: true
namespace: "text"
@@ -20,13 +12,6 @@
}
flag {
- name: "fix_double_underline"
- namespace: "text"
- description: "Feature flag for fixing double underline because of the multiple font used in the single line."
- bug: "297336724"
-}
-
-flag {
name: "fix_line_height_for_locale"
is_exported: true
namespace: "text"
@@ -66,13 +51,6 @@
}
flag {
- name: "phrase_strict_fallback"
- namespace: "text"
- description: "Feature flag for automatic fallback from phrase based line break to strict line break."
- bug: "281970875"
-}
-
-flag {
name: "use_bounds_for_width"
is_exported: true
namespace: "text"
diff --git a/core/java/android/tracing/flags.aconfig b/core/java/android/tracing/flags.aconfig
index 04dba46..fb1bd17 100644
--- a/core/java/android/tracing/flags.aconfig
+++ b/core/java/android/tracing/flags.aconfig
@@ -48,6 +48,22 @@
}
flag {
+ name: "perfetto_wm_dump"
+ namespace: "windowing_tools"
+ description: "Migrate WindowManager dump to Perfetto"
+ is_fixed_read_only: true
+ bug: "323165543"
+}
+
+flag {
+ name: "perfetto_wm_dump_cts"
+ namespace: "windowing_tools"
+ description: "Migrate WindowManager dump in CTS tests to Perfetto"
+ is_fixed_read_only: true
+ bug: "323165543"
+}
+
+flag {
name: "client_side_proto_logging"
namespace: "windowing_tools"
description: "Add support for client side protologging"
diff --git a/core/java/android/tracing/perfetto/DataSource.java b/core/java/android/tracing/perfetto/DataSource.java
index 4de7b62..b65471d 100644
--- a/core/java/android/tracing/perfetto/DataSource.java
+++ b/core/java/android/tracing/perfetto/DataSource.java
@@ -16,6 +16,8 @@
package android.tracing.perfetto;
+import android.annotation.Nullable;
+import android.annotation.NonNull;
import android.util.proto.ProtoInputStream;
/**
@@ -41,6 +43,7 @@
* @param configStream A ProtoInputStream to read the tracing instance's config.
* @return A new data source instance setup with the provided config.
*/
+ @NonNull
public abstract DataSourceInstanceType createInstance(
ProtoInputStream configStream, int instanceIndex);
@@ -102,8 +105,8 @@
/**
* Override this method to create a custom TlsState object for your DataSource. A new instance
* will be created per trace instance per thread.
- *
*/
+ @Nullable
public TlsStateType createTlsState(CreateTlsStateArgs<DataSourceInstanceType> args) {
return null;
}
@@ -112,6 +115,7 @@
* Override this method to create and use a custom IncrementalState object for your DataSource.
*
*/
+ @Nullable
public IncrementalStateType createIncrementalState(
CreateIncrementalStateArgs<DataSourceInstanceType> args) {
return null;
@@ -141,6 +145,7 @@
* @return The DataSourceInstance at index instanceIndex.
* Null if the datasource instance at the requested index doesn't exist.
*/
+ @Nullable
public DataSourceInstanceType getDataSourceInstanceLocked(int instanceIndex) {
return (DataSourceInstanceType) nativeGetPerfettoInstanceLocked(mNativeObj, instanceIndex);
}
@@ -159,6 +164,7 @@
* @param rawConfig byte array of the PerfettoConfig encoded proto.
* @return A new Java DataSourceInstance object.
*/
+ @NonNull
private DataSourceInstanceType createInstance(byte[] rawConfig, int instanceIndex) {
final ProtoInputStream inputStream = new ProtoInputStream(rawConfig);
return this.createInstance(inputStream, instanceIndex);
diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java
index 0a73fd1..00545da 100644
--- a/core/java/android/util/EventLog.java
+++ b/core/java/android/util/EventLog.java
@@ -21,6 +21,10 @@
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
+import android.ravenwood.annotation.RavenwoodThrow;
import java.io.BufferedReader;
import java.io.FileReader;
@@ -48,9 +52,8 @@
* They carry a payload of one or more int, long, or String values. The
* event-log-tags file defines the payload contents for each type code.
*/
-@android.ravenwood.annotation.RavenwoodKeepWholeClass
-@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
- "com.android.platform.test.ravenwood.nativesubstitution.EventLog_host")
+@RavenwoodKeepWholeClass
+@RavenwoodRedirectionClass("EventLog_host")
public class EventLog {
/** @hide */ public EventLog() {}
@@ -339,6 +342,7 @@
* @param value A value to log
* @return The number of bytes written
*/
+ @RavenwoodRedirect
public static native int writeEvent(int tag, int value);
/**
@@ -347,6 +351,7 @@
* @param value A value to log
* @return The number of bytes written
*/
+ @RavenwoodRedirect
public static native int writeEvent(int tag, long value);
/**
@@ -355,6 +360,7 @@
* @param value A value to log
* @return The number of bytes written
*/
+ @RavenwoodRedirect
public static native int writeEvent(int tag, float value);
/**
@@ -363,6 +369,7 @@
* @param str A value to log
* @return The number of bytes written
*/
+ @RavenwoodRedirect
public static native int writeEvent(int tag, String str);
/**
@@ -371,6 +378,7 @@
* @param list A list of values to log
* @return The number of bytes written
*/
+ @RavenwoodRedirect
public static native int writeEvent(int tag, Object... list);
/**
@@ -379,6 +387,7 @@
* @param output container to add events into
* @throws IOException if something goes wrong reading events
*/
+ @RavenwoodThrow
public static native void readEvents(int[] tags, Collection<Event> output)
throws IOException;
@@ -391,6 +400,7 @@
* @hide
*/
@SystemApi
+ @RavenwoodThrow
public static native void readEventsOnWrapping(int[] tags, long timestamp,
Collection<Event> output)
throws IOException;
diff --git a/core/java/android/util/LocalLog.java b/core/java/android/util/LocalLog.java
index feb80cc..ca5798a 100644
--- a/core/java/android/util/LocalLog.java
+++ b/core/java/android/util/LocalLog.java
@@ -112,6 +112,11 @@
}
}
+ // @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+ public synchronized void clear() {
+ mLog.clear();
+ }
+
public static class ReadOnlyLocalLog {
private final LocalLog mLog;
ReadOnlyLocalLog(LocalLog log) {
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 9e4b27d..2dda835 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -445,16 +445,20 @@
// Jank due to unknown reasons.
public static final int UNKNOWN = 0x80;
- public JankData(long frameVsyncId, @JankType int jankType, long frameIntervalNs) {
+ public JankData(long frameVsyncId, @JankType int jankType, long frameIntervalNs,
+ long scheduledAppFrameTimeNs, long actualAppFrameTimeNs) {
this.frameVsyncId = frameVsyncId;
this.jankType = jankType;
this.frameIntervalNs = frameIntervalNs;
-
+ this.scheduledAppFrameTimeNs = scheduledAppFrameTimeNs;
+ this.actualAppFrameTimeNs = actualAppFrameTimeNs;
}
public final long frameVsyncId;
public final @JankType int jankType;
public final long frameIntervalNs;
+ public final long scheduledAppFrameTimeNs;
+ public final long actualAppFrameTimeNs;
}
/**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 523ff38..7b4ea41 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -27377,6 +27377,29 @@
}
/**
+ * Modifiers the input matrix such that it maps root view's coordinates to view-local
+ * coordinates.
+ *
+ * @param matrix input matrix to modify
+ * @hide
+ */
+ public void transformMatrixRootToLocal(@NonNull Matrix matrix) {
+ final ViewParent parent = mParent;
+ if (parent instanceof final View vp) {
+ vp.transformMatrixRootToLocal(matrix);
+ matrix.postTranslate(vp.mScrollX, vp.mScrollY);
+ }
+ // This method is different from transformMatrixToLocal that it doesn't perform any
+ // transformation for ViewRootImpl
+
+ matrix.postTranslate(-mLeft, -mTop);
+
+ if (!hasIdentityMatrix()) {
+ matrix.postConcat(getInverseMatrix());
+ }
+ }
+
+ /**
* @hide
*/
@ViewDebug.ExportedProperty(category = "layout", indexMapping = {
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index fb2b8b9..63bf392 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -373,6 +373,7 @@
private final int mMaximumDrawingCacheSize;
private final int mOverscrollDistance;
private final int mOverflingDistance;
+ private final boolean mViewTouchScreenHapticScrollFeedbackEnabled;
@UnsupportedAppUsage
private final boolean mFadingMarqueeEnabled;
private final long mGlobalActionsKeyTimeout;
@@ -437,6 +438,7 @@
mSmartSelectionInitializedTimeout = SMART_SELECTION_INITIALIZED_TIMEOUT_IN_MILLISECOND;
mSmartSelectionInitializingTimeout = SMART_SELECTION_INITIALIZING_TIMEOUT_IN_MILLISECOND;
mPreferKeepClearForFocusEnabled = false;
+ mViewTouchScreenHapticScrollFeedbackEnabled = false;
}
/**
@@ -588,6 +590,12 @@
mViewBasedRotaryEncoderScrollHapticsEnabledConfig =
res.getBoolean(
com.android.internal.R.bool.config_viewBasedRotaryEncoderHapticsEnabled);
+ mViewTouchScreenHapticScrollFeedbackEnabled =
+ Flags.enableTouchScrollFeedback()
+ ? res.getBoolean(
+ com.android.internal.R.bool
+ .config_viewTouchScreenHapticScrollFeedbackEnabled)
+ : false;
}
/**
@@ -1285,6 +1293,10 @@
return mRotaryEncoderHapticScrollFeedbackEnabled;
}
+ if ((source & InputDevice.SOURCE_TOUCHSCREEN) != 0) {
+ return mViewTouchScreenHapticScrollFeedbackEnabled;
+ }
+
return false;
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f021bdf..e10cc28 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4345,6 +4345,7 @@
handleSyncRequestWhenNoAsyncDraw(mActiveSurfaceSyncGroup, mHasPendingTransactions,
mPendingTransaction, "view not visible");
+ mHasPendingTransactions = false;
} else if (cancelAndRedraw) {
if (!mWasLastDrawCanceled) {
logAndTrace("Canceling draw."
@@ -4372,6 +4373,7 @@
if (!performDraw(mActiveSurfaceSyncGroup)) {
handleSyncRequestWhenNoAsyncDraw(mActiveSurfaceSyncGroup, mHasPendingTransactions,
mPendingTransaction, mLastPerformDrawSkippedReason);
+ mHasPendingTransactions = false;
}
}
mWasLastDrawCanceled = cancelAndRedraw;
@@ -4388,7 +4390,14 @@
mReportNextDraw = false;
mLastReportNextDrawReason = null;
mActiveSurfaceSyncGroup = null;
- mHasPendingTransactions = false;
+ if (mHasPendingTransactions) {
+ // TODO: We shouldn't ever actually hit this, it means mPendingTransaction wasn't
+ // merged with a sync group or BLASTBufferQueue before making it to this point
+ // But better a one or two frame flicker than steady-state broken from dropping
+ // whatever is in this transaction
+ mPendingTransaction.apply();
+ mHasPendingTransactions = false;
+ }
mSyncBuffer = false;
if (isInWMSRequestedSync()) {
mWmsRequestSyncGroup.markSyncReady();
@@ -5305,6 +5314,7 @@
private void registerCallbackForPendingTransactions() {
Transaction t = new Transaction();
t.merge(mPendingTransaction);
+ mHasPendingTransactions = false;
registerRtFrameCallback(new FrameDrawingCallback() {
@Override
@@ -5384,6 +5394,7 @@
if (!usingAsyncReport && mHasPendingTransactions) {
pendingTransaction = new Transaction();
pendingTransaction.merge(mPendingTransaction);
+ mHasPendingTransactions = false;
} else {
pendingTransaction = null;
}
@@ -9942,6 +9953,7 @@
}
handleSyncRequestWhenNoAsyncDraw(mActiveSurfaceSyncGroup, mHasPendingTransactions,
mPendingTransaction, "shutting down VRI");
+ mHasPendingTransactions = false;
WindowManagerGlobal.getInstance().doRemoveView(this);
}
@@ -12601,6 +12613,7 @@
if (mHasPendingTransactions) {
t = new Transaction();
t.merge(mPendingTransaction);
+ mHasPendingTransactions = false;
} else {
t = null;
}
diff --git a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
index ed2bf79..513587e 100644
--- a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
+++ b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig
@@ -19,6 +19,13 @@
}
flag {
+ name: "a11y_selection_api"
+ namespace: "accessibility"
+ description: "Enables new APIs for an AccessibilityService to control selection across nodes."
+ bug: "362782866"
+}
+
+flag {
namespace: "accessibility"
name: "allow_shortcut_chooser_on_lockscreen"
description: "Allows the a11y shortcut disambig dialog to appear on the lockscreen"
diff --git a/core/java/android/view/flags/scroll_feedback_flags.aconfig b/core/java/android/view/flags/scroll_feedback_flags.aconfig
index 338037f..e9c85684 100644
--- a/core/java/android/view/flags/scroll_feedback_flags.aconfig
+++ b/core/java/android/view/flags/scroll_feedback_flags.aconfig
@@ -14,4 +14,11 @@
name: "use_view_based_rotary_encoder_scroll_haptics"
description: "If enabled, the rotary encoder scroll haptic implementation in the View class will be used, and the HapticScrollFeedbackProvider logic for rotary encoder haptic will be muted."
bug: "299587011"
-}
\ No newline at end of file
+}
+
+flag {
+ namespace: "toolkit"
+ name: "enable_touch_scroll_feedback"
+ description: "Enables touchscreen haptic scroll feedback"
+ bug: "331830899"
+}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index f336b5d..ffe8c80 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -3088,11 +3088,11 @@
}
if (Flags.updateServiceIpcWrapper()) {
- WebViewUpdateManager manager = WebViewUpdateManager.getInstance();
- if (manager == null) {
+ if (WebViewFactory.isWebViewSupported()) {
+ return WebViewUpdateManager.getInstance().getCurrentWebViewPackage();
+ } else {
return null;
}
- return manager.getCurrentWebViewPackage();
} else {
IWebViewUpdateService service = WebViewFactory.getUpdateService();
if (service == null) {
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index f532934..e10a398 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -208,7 +208,7 @@
public MissingWebViewPackageException(Exception e) { super(e); }
}
- private static boolean isWebViewSupported() {
+ static boolean isWebViewSupported() {
// No lock; this is a benign race as Boolean's state is final and the PackageManager call
// will always return the same value.
if (sWebViewSupported == null) {
diff --git a/core/java/android/webkit/WebViewUpdateManager.java b/core/java/android/webkit/WebViewUpdateManager.java
index dd48df9..0eb71001 100644
--- a/core/java/android/webkit/WebViewUpdateManager.java
+++ b/core/java/android/webkit/WebViewUpdateManager.java
@@ -19,12 +19,14 @@
import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.app.SystemServiceRegistry;
import android.content.Context;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.os.RemoteException;
/** @hide */
@@ -43,8 +45,11 @@
*
* This exists for the benefit of callsites without a {@link Context}; prefer
* {@link Context#getSystemService(Class)} otherwise.
+ *
+ * This can only be used on devices with {@link PackageManager#FEATURE_WEBVIEW}.
*/
@SuppressLint("ManagerLookup") // service opts in to getSystemServiceWithNoContext()
+ @RequiresFeature(PackageManager.FEATURE_WEBVIEW)
public static @Nullable WebViewUpdateManager getInstance() {
return (WebViewUpdateManager) SystemServiceRegistry.getSystemServiceWithNoContext(
Context.WEBVIEW_UPDATE_SERVICE);
diff --git a/core/java/android/webkit/WebViewUpdateService.java b/core/java/android/webkit/WebViewUpdateService.java
index 6f53dde..01af182 100644
--- a/core/java/android/webkit/WebViewUpdateService.java
+++ b/core/java/android/webkit/WebViewUpdateService.java
@@ -34,11 +34,11 @@
*/
public static WebViewProviderInfo[] getAllWebViewPackages() {
if (Flags.updateServiceIpcWrapper()) {
- WebViewUpdateManager manager = WebViewUpdateManager.getInstance();
- if (manager == null) {
+ if (WebViewFactory.isWebViewSupported()) {
+ return WebViewUpdateManager.getInstance().getAllWebViewPackages();
+ } else {
return new WebViewProviderInfo[0];
}
- return manager.getAllWebViewPackages();
} else {
IWebViewUpdateService service = getUpdateService();
if (service == null) {
@@ -57,11 +57,11 @@
*/
public static WebViewProviderInfo[] getValidWebViewPackages() {
if (Flags.updateServiceIpcWrapper()) {
- WebViewUpdateManager manager = WebViewUpdateManager.getInstance();
- if (manager == null) {
+ if (WebViewFactory.isWebViewSupported()) {
+ return WebViewUpdateManager.getInstance().getValidWebViewPackages();
+ } else {
return new WebViewProviderInfo[0];
}
- return manager.getValidWebViewPackages();
} else {
IWebViewUpdateService service = getUpdateService();
if (service == null) {
@@ -80,11 +80,11 @@
*/
public static String getCurrentWebViewPackageName() {
if (Flags.updateServiceIpcWrapper()) {
- WebViewUpdateManager manager = WebViewUpdateManager.getInstance();
- if (manager == null) {
+ if (WebViewFactory.isWebViewSupported()) {
+ return WebViewUpdateManager.getInstance().getCurrentWebViewPackageName();
+ } else {
return null;
}
- return manager.getCurrentWebViewPackageName();
} else {
IWebViewUpdateService service = getUpdateService();
if (service == null) {
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index ab6b512..3c854ea 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -16,6 +16,8 @@
package android.widget;
+import static android.view.flags.Flags.enableTouchScrollFeedback;
+import static android.view.flags.Flags.scrollFeedbackApi;
import static android.view.flags.Flags.viewVelocityApi;
import android.annotation.ColorInt;
@@ -82,7 +84,6 @@
import android.view.autofill.AutofillId;
import android.view.contentcapture.ContentCaptureManager;
import android.view.contentcapture.ContentCaptureSession;
-import android.view.flags.Flags;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
@@ -3703,7 +3704,6 @@
// If it's non-null, we're already in a scroll.
mScrollStrictSpan = StrictMode.enterCriticalSpan("AbsListView-scroll");
}
-
if (y != mLastY) {
// We may be here after stopping a fling and continuing to scroll.
// If so, we haven't disallowed intercepting touch events yet.
@@ -3735,8 +3735,15 @@
boolean atEdge = false;
if (incrementalDeltaY != 0) {
atEdge = trackMotionScroll(deltaY, incrementalDeltaY);
- }
+ // TODO: b/360198915 - Add unit testing for using ScrollFeedbackProvider
+ if (enableTouchScrollFeedback()) {
+ initHapticScrollFeedbackProviderIfNotExists();
+ mHapticScrollFeedbackProvider.onScrollProgress(
+ vtev.getDeviceId(), vtev.getSource(), MotionEvent.AXIS_Y,
+ incrementalDeltaY);
+ }
+ }
// Check to see if we have bumped into the scroll limit
motionView = this.getChildAt(motionIndex);
if (motionView != null) {
@@ -3745,7 +3752,6 @@
final int motionViewRealTop = motionView.getTop();
if (atEdge) {
// Apply overscroll
-
int overscroll = -incrementalDeltaY -
(motionViewRealTop - motionViewPrevTop);
if (dispatchNestedScroll(0, overscroll - incrementalDeltaY, 0, overscroll,
@@ -3772,6 +3778,15 @@
mDirection = 0; // Reset when entering overscroll.
mTouchMode = TOUCH_MODE_OVERSCROLL;
}
+
+ if (enableTouchScrollFeedback()) {
+ initHapticScrollFeedbackProviderIfNotExists();
+ mHapticScrollFeedbackProvider.onScrollLimit(
+ vtev.getDeviceId(), vtev.getSource(),
+ MotionEvent.AXIS_Y,
+ /* isStart= */ incrementalDeltaY > 0);
+ }
+
if (incrementalDeltaY > 0) {
mEdgeGlowTop.onPullDistance((float) -overscroll / getHeight(),
(float) x / getWidth());
@@ -3981,7 +3996,6 @@
if (mFastScroll != null && mFastScroll.onTouchEvent(ev)) {
return true;
}
-
initVelocityTrackerIfNotExists();
final MotionEvent vtev = MotionEvent.obtain(ev);
@@ -4520,7 +4534,7 @@
final int overscrollMode = getOverScrollMode();
if (!trackMotionScroll(delta, delta)) {
- if (Flags.scrollFeedbackApi()) {
+ if (scrollFeedbackApi()) {
initHapticScrollFeedbackProviderIfNotExists();
mHapticScrollFeedbackProvider.onScrollProgress(
event.getDeviceId(), event.getSource(), axis, delta);
@@ -4536,7 +4550,7 @@
float overscroll = (delta - (motionViewRealTop - motionViewPrevTop))
/ ((float) getHeight());
boolean hitTopLimit = delta > 0;
- if (Flags.scrollFeedbackApi()) {
+ if (scrollFeedbackApi()) {
initHapticScrollFeedbackProviderIfNotExists();
mHapticScrollFeedbackProvider.onScrollLimit(
event.getDeviceId(), event.getSource(), axis,
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index eb35817..a395c1a 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1447,6 +1447,11 @@
}
@Override
+ public void onNullBinding(ComponentName name) {
+ context.unbindService(this);
+ }
+
+ @Override
public void onServiceDisconnected(ComponentName componentName) { }
});
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 2f28a87..118edc2 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -241,6 +241,11 @@
}
@Override
+ public void onNullBinding(ComponentName name) {
+ enqueueDeferredUnbindServiceMessage();
+ }
+
+ @Override
public void handleMessage(Message msg) {
RemoteViewsAdapter adapter = mAdapter.get();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a346a67..ef941da 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1659,11 +1659,7 @@
}
if (!hasUseBoundForWidthValue) {
- if (CompatChanges.isChangeEnabled(USE_BOUNDS_FOR_WIDTH)) {
- mUseBoundsForWidth = Flags.useBoundsForWidth();
- } else {
- mUseBoundsForWidth = false;
- }
+ mUseBoundsForWidth = CompatChanges.isChangeEnabled(USE_BOUNDS_FOR_WIDTH);
}
// TODO(b/179693024): Use a ChangeId instead.
@@ -14375,7 +14371,7 @@
Matrix matrix = mTempMatrix;
matrix.reset();
- transformMatrixToLocal(matrix);
+ transformMatrixRootToLocal(matrix);
editorBounds.set(rect);
// When the view has transformations like scaleX/scaleY computing the global visible
// rectangle will already apply the transformations. The getLocalVisibleRect only offsets
diff --git a/core/java/android/window/BackAnimationAdapter.java b/core/java/android/window/BackAnimationAdapter.java
index 5eb34e6..153e153 100644
--- a/core/java/android/window/BackAnimationAdapter.java
+++ b/core/java/android/window/BackAnimationAdapter.java
@@ -16,9 +16,12 @@
package android.window;
+import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.ArrayList;
+
/**
* Object that describes how to run a remote back animation.
*
@@ -26,6 +29,7 @@
*/
public class BackAnimationAdapter implements Parcelable {
private final IBackAnimationRunner mRunner;
+ private int[] mSupportedAnimators;
public BackAnimationAdapter(IBackAnimationRunner runner) {
mRunner = runner;
@@ -33,12 +37,23 @@
public BackAnimationAdapter(Parcel in) {
mRunner = IBackAnimationRunner.Stub.asInterface(in.readStrongBinder());
+ mSupportedAnimators = new int[in.readInt()];
+ in.readIntArray(mSupportedAnimators);
}
public IBackAnimationRunner getRunner() {
return mRunner;
}
+ /** Update the latest animators in the system. */
+ public void updateSupportedAnimators(@NonNull ArrayList<Integer> animators) {
+ final int size = animators.size();
+ mSupportedAnimators = new int[size];
+ for (int i = size - 1; i >= 0; --i) {
+ mSupportedAnimators[i] = animators.get(i);
+ }
+ }
+
@Override
public int describeContents() {
return 0;
@@ -47,6 +62,8 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeStrongInterface(mRunner);
+ dest.writeInt(mSupportedAnimators.length);
+ dest.writeIntArray(mSupportedAnimators);
}
public static final @android.annotation.NonNull Creator<BackAnimationAdapter> CREATOR =
@@ -59,4 +76,19 @@
return new BackAnimationAdapter[size];
}
};
+
+ /**
+ * Check if the back type is animatable.
+ */
+ public boolean isAnimatable(@BackNavigationInfo.BackTargetType int backType) {
+ if (mSupportedAnimators == null) {
+ return false;
+ }
+ for (int i = mSupportedAnimators.length - 1; i >= 0; --i) {
+ if (backType == mSupportedAnimators[i]) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/core/java/android/window/SnapshotDrawerUtils.java b/core/java/android/window/SnapshotDrawerUtils.java
index 2f595d1..9a7bce0 100644
--- a/core/java/android/window/SnapshotDrawerUtils.java
+++ b/core/java/android/window/SnapshotDrawerUtils.java
@@ -151,9 +151,11 @@
@VisibleForTesting
public void setFrames(Rect frame, Rect systemBarInsets) {
mFrame.set(frame);
- mSystemBarInsets.set(systemBarInsets);
mSizeMismatch = (mFrame.width() != mSnapshotW || mFrame.height() != mSnapshotH);
- mSystemBarBackgroundPainter.setInsets(systemBarInsets);
+ if (!Flags.drawSnapshotAspectRatioMatch() && systemBarInsets != null) {
+ mSystemBarInsets.set(systemBarInsets);
+ mSystemBarBackgroundPainter.setInsets(systemBarInsets);
+ }
}
private void drawSnapshot(boolean releaseAfterDraw) {
@@ -394,9 +396,12 @@
final ActivityManager.RunningTaskInfo runningTaskInfo = info.taskInfo;
final ActivityManager.TaskDescription taskDescription =
getOrCreateTaskDescription(runningTaskInfo);
- drawSurface.initiateSystemBarPainter(lp.flags, lp.privateFlags,
- attrs.insetsFlags.appearance, taskDescription, info.requestedVisibleTypes);
- final Rect systemBarInsets = getSystemBarInsets(windowBounds, topWindowInsetsState);
+ Rect systemBarInsets = null;
+ if (!Flags.drawSnapshotAspectRatioMatch()) {
+ drawSurface.initiateSystemBarPainter(lp.flags, lp.privateFlags,
+ attrs.insetsFlags.appearance, taskDescription, info.requestedVisibleTypes);
+ systemBarInsets = getSystemBarInsets(windowBounds, topWindowInsetsState);
+ }
drawSurface.setFrames(windowBounds, systemBarInsets);
drawSurface.drawSnapshot(releaseAfterDraw);
}
diff --git a/core/java/android/window/TaskFragmentOrganizer.java b/core/java/android/window/TaskFragmentOrganizer.java
index 4cc0d8a..c3168001 100644
--- a/core/java/android/window/TaskFragmentOrganizer.java
+++ b/core/java/android/window/TaskFragmentOrganizer.java
@@ -69,6 +69,23 @@
public static final String KEY_ERROR_CALLBACK_OP_TYPE = "operation_type";
/**
+ * Key to bundle {@link TaskFragmentInfo}s from the system in
+ * {@link #registerOrganizer(boolean, Bundle)}
+ *
+ * @hide
+ */
+ public static final String KEY_RESTORE_TASK_FRAGMENTS_INFO = "key_restore_task_fragments_info";
+
+ /**
+ * Key to bundle {@link TaskFragmentParentInfo} from the system in
+ * {@link #registerOrganizer(boolean, Bundle)}
+ *
+ * @hide
+ */
+ public static final String KEY_RESTORE_TASK_FRAGMENT_PARENT_INFO =
+ "key_restore_task_fragment_parent_info";
+
+ /**
* No change set.
*/
@WindowManager.TransitionType
diff --git a/core/java/android/window/TaskFragmentParentInfo.java b/core/java/android/window/TaskFragmentParentInfo.java
index 1555416..efd74c3 100644
--- a/core/java/android/window/TaskFragmentParentInfo.java
+++ b/core/java/android/window/TaskFragmentParentInfo.java
@@ -41,6 +41,8 @@
private final int mDisplayId;
+ private final int mTaskId;
+
private final boolean mVisible;
private final boolean mHasDirectActivity;
@@ -49,9 +51,11 @@
/** @hide */
public TaskFragmentParentInfo(@NonNull Configuration configuration, int displayId,
- boolean visible, boolean hasDirectActivity, @Nullable SurfaceControl decorSurface) {
+ int taskId, boolean visible, boolean hasDirectActivity,
+ @Nullable SurfaceControl decorSurface) {
mConfiguration.setTo(configuration);
mDisplayId = displayId;
+ mTaskId = taskId;
mVisible = visible;
mHasDirectActivity = hasDirectActivity;
mDecorSurface = decorSurface;
@@ -61,6 +65,7 @@
public TaskFragmentParentInfo(@NonNull TaskFragmentParentInfo info) {
mConfiguration.setTo(info.getConfiguration());
mDisplayId = info.mDisplayId;
+ mTaskId = info.mTaskId;
mVisible = info.mVisible;
mHasDirectActivity = info.mHasDirectActivity;
mDecorSurface = info.mDecorSurface;
@@ -87,6 +92,15 @@
}
/**
+ * The id of the parent Task.
+ *
+ * @hide
+ */
+ public int getTaskId() {
+ return mTaskId;
+ }
+
+ /**
* Whether the parent Task is visible or not
*
* @hide
@@ -120,7 +134,8 @@
return false;
}
return getWindowingMode() == that.getWindowingMode() && mDisplayId == that.mDisplayId
- && mVisible == that.mVisible && mHasDirectActivity == that.mHasDirectActivity
+ && mTaskId == that.mTaskId && mVisible == that.mVisible
+ && mHasDirectActivity == that.mHasDirectActivity
&& mDecorSurface == that.mDecorSurface;
}
@@ -140,6 +155,7 @@
return TaskFragmentParentInfo.class.getSimpleName() + ":{"
+ "config=" + mConfiguration
+ ", displayId=" + mDisplayId
+ + ", taskId=" + mTaskId
+ ", visible=" + mVisible
+ ", hasDirectActivity=" + mHasDirectActivity
+ ", decorSurface=" + mDecorSurface
@@ -163,6 +179,7 @@
final TaskFragmentParentInfo that = (TaskFragmentParentInfo) obj;
return mConfiguration.equals(that.mConfiguration)
&& mDisplayId == that.mDisplayId
+ && mTaskId == that.mTaskId
&& mVisible == that.mVisible
&& mHasDirectActivity == that.mHasDirectActivity
&& mDecorSurface == that.mDecorSurface;
@@ -172,6 +189,7 @@
public int hashCode() {
int result = mConfiguration.hashCode();
result = 31 * result + mDisplayId;
+ result = 31 * result + mTaskId;
result = 31 * result + (mVisible ? 1 : 0);
result = 31 * result + (mHasDirectActivity ? 1 : 0);
result = 31 * result + Objects.hashCode(mDecorSurface);
@@ -183,6 +201,7 @@
public void writeToParcel(@NonNull Parcel dest, int flags) {
mConfiguration.writeToParcel(dest, flags);
dest.writeInt(mDisplayId);
+ dest.writeInt(mTaskId);
dest.writeBoolean(mVisible);
dest.writeBoolean(mHasDirectActivity);
dest.writeTypedObject(mDecorSurface, flags);
@@ -191,6 +210,7 @@
private TaskFragmentParentInfo(Parcel in) {
mConfiguration.readFromParcel(in);
mDisplayId = in.readInt();
+ mTaskId = in.readInt();
mVisible = in.readBoolean();
mHasDirectActivity = in.readBoolean();
mDecorSurface = in.readTypedObject(SurfaceControl.CREATOR);
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index ec79f94..1083f64 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -1141,7 +1141,6 @@
// Customize activity transition animation
private CustomActivityTransition mCustomActivityOpenTransition;
private CustomActivityTransition mCustomActivityCloseTransition;
- private int mUserId;
private AnimationOptions(int type) {
mType = type;
@@ -1160,7 +1159,6 @@
mAnimations = in.readInt();
mCustomActivityOpenTransition = in.readTypedObject(CustomActivityTransition.CREATOR);
mCustomActivityCloseTransition = in.readTypedObject(CustomActivityTransition.CREATOR);
- mUserId = in.readInt();
}
/** Make basic customized animation for a package */
@@ -1285,14 +1283,6 @@
return options;
}
- public void setUserId(int userId) {
- mUserId = userId;
- }
-
- public int getUserId() {
- return mUserId;
- }
-
public int getType() {
return mType;
}
@@ -1359,7 +1349,6 @@
dest.writeInt(mAnimations);
dest.writeTypedObject(mCustomActivityOpenTransition, flags);
dest.writeTypedObject(mCustomActivityCloseTransition, flags);
- dest.writeInt(mUserId);
}
@NonNull
@@ -1417,7 +1406,6 @@
if (mExitResId != DEFAULT_ANIMATION_RESOURCES_ID) {
sb.append(" exitResId=").append(mExitResId);
}
- sb.append(" mUserId=").append(mUserId);
sb.append('}');
return sb.toString();
}
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index ebf87f1..3998ac6 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -2,14 +2,6 @@
container: "system"
flag {
- name: "enable_scaled_resizing"
- namespace: "lse_desktop_experience"
- description: "Enable the resizing of un-resizable apps through scaling their bounds up/down"
- bug: "320350734"
- is_fixed_read_only: true
-}
-
-flag {
name: "enable_desktop_windowing_mode"
namespace: "lse_desktop_experience"
description: "Enables desktop windowing"
@@ -31,6 +23,13 @@
}
flag {
+ name: "enable_windowing_scaled_resizing"
+ namespace: "lse_desktop_experience"
+ description: "Enables the resizing of non-resizable apps through scaling their bounds up/down"
+ bug: "319844447"
+}
+
+flag {
name: "disable_non_resizable_app_snap_resizing"
namespace: "lse_desktop_experience"
description: "Stops non-resizable app desktop windows from being snap resized"
@@ -245,3 +244,10 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "enable_desktop_windowing_persistence"
+ namespace: "lse_desktop_experience"
+ description: "Persists the desktop windowing session across reboots."
+ bug: "350456942"
+}
diff --git a/core/java/com/android/internal/app/LocalePickerWithRegion.java b/core/java/com/android/internal/app/LocalePickerWithRegion.java
index ce17d78..ef4acd1 100644
--- a/core/java/com/android/internal/app/LocalePickerWithRegion.java
+++ b/core/java/com/android/internal/app/LocalePickerWithRegion.java
@@ -23,6 +23,7 @@
import android.os.Bundle;
import android.os.LocaleList;
import android.text.TextUtils;
+import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -265,6 +266,11 @@
public void onListItemClick(ListView parent, View v, int position, long id) {
final LocaleStore.LocaleInfo locale =
(LocaleStore.LocaleInfo) parent.getAdapter().getItem(position);
+ if (locale == null) {
+ Log.d(TAG, "Can not get the locale.");
+ return;
+ }
+
// Special case for resetting the app locale to equal the system locale.
boolean isSystemLocale = locale.isSystemLocale();
boolean isRegionLocale = locale.getParent() != null;
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index 53ef49b..d474c6d 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -127,7 +127,7 @@
private Runnable mWaitForFinishTimedOut;
private static class JankInfo {
- long frameVsyncId;
+ final long frameVsyncId;
long totalDurationNanos;
boolean isFirstFrame;
boolean hwuiCallbackFired;
@@ -135,29 +135,42 @@
@JankType int jankType;
@RefreshRate int refreshRate;
- static JankInfo createFromHwuiCallback(long frameVsyncId, long totalDurationNanos,
- boolean isFirstFrame) {
- return new JankInfo(frameVsyncId, true, false, JANK_NONE, UNKNOWN_REFRESH_RATE,
- totalDurationNanos, isFirstFrame);
+ static JankInfo createFromHwuiCallback(
+ long frameVsyncId, long totalDurationNanos, boolean isFirstFrame) {
+ return new JankInfo(frameVsyncId).update(totalDurationNanos, isFirstFrame);
}
- static JankInfo createFromSurfaceControlCallback(long frameVsyncId,
- @JankType int jankType, @RefreshRate int refreshRate) {
- return new JankInfo(
- frameVsyncId, false, true, jankType, refreshRate, 0, false /* isFirstFrame */);
+ static JankInfo createFromSurfaceControlCallback(SurfaceControl.JankData jankStat) {
+ return new JankInfo(jankStat.frameVsyncId).update(jankStat);
}
- private JankInfo(long frameVsyncId, boolean hwuiCallbackFired,
- boolean surfaceControlCallbackFired, @JankType int jankType,
- @RefreshRate int refreshRate,
- long totalDurationNanos, boolean isFirstFrame) {
+ private JankInfo(long frameVsyncId) {
this.frameVsyncId = frameVsyncId;
- this.hwuiCallbackFired = hwuiCallbackFired;
- this.surfaceControlCallbackFired = surfaceControlCallbackFired;
- this.jankType = jankType;
- this.refreshRate = refreshRate;
- this.totalDurationNanos = totalDurationNanos;
+ this.hwuiCallbackFired = false;
+ this.surfaceControlCallbackFired = false;
+ this.jankType = JANK_NONE;
+ this.refreshRate = UNKNOWN_REFRESH_RATE;
+ this.totalDurationNanos = 0;
+ this.isFirstFrame = false;
+ }
+
+ private JankInfo update(SurfaceControl.JankData jankStat) {
+ this.surfaceControlCallbackFired = true;
+ this.jankType = jankStat.jankType;
+ this.refreshRate = DisplayRefreshRate.getRefreshRate(jankStat.frameIntervalNs);
+ if (Flags.useSfFrameDuration()) {
+ this.totalDurationNanos = jankStat.actualAppFrameTimeNs;
+ }
+ return this;
+ }
+
+ private JankInfo update(long totalDurationNanos, boolean isFirstFrame) {
+ this.hwuiCallbackFired = true;
+ if (!Flags.useSfFrameDuration()) {
+ this.totalDurationNanos = totalDurationNanos;
+ }
this.isFirstFrame = isFirstFrame;
+ return this;
}
@Override
@@ -457,16 +470,12 @@
if (!isInRange(jankStat.frameVsyncId)) {
continue;
}
- int refreshRate = DisplayRefreshRate.getRefreshRate(jankStat.frameIntervalNs);
JankInfo info = findJankInfo(jankStat.frameVsyncId);
if (info != null) {
- info.surfaceControlCallbackFired = true;
- info.jankType = jankStat.jankType;
- info.refreshRate = refreshRate;
+ info.update(jankStat);
} else {
mJankInfos.put((int) jankStat.frameVsyncId,
- JankInfo.createFromSurfaceControlCallback(
- jankStat.frameVsyncId, jankStat.jankType, refreshRate));
+ JankInfo.createFromSurfaceControlCallback(jankStat));
}
}
processJankInfos();
@@ -513,9 +522,7 @@
}
JankInfo info = findJankInfo(frameVsyncId);
if (info != null) {
- info.hwuiCallbackFired = true;
- info.totalDurationNanos = totalDurationNanos;
- info.isFirstFrame = isFirstFrame;
+ info.update(totalDurationNanos, isFirstFrame);
} else {
mJankInfos.put((int) frameVsyncId, JankInfo.createFromHwuiCallback(
frameVsyncId, totalDurationNanos, isFirstFrame));
diff --git a/core/java/com/android/internal/jank/flags.aconfig b/core/java/com/android/internal/jank/flags.aconfig
new file mode 100644
index 0000000..b6b8bc5
--- /dev/null
+++ b/core/java/com/android/internal/jank/flags.aconfig
@@ -0,0 +1,10 @@
+package: "com.android.internal.jank"
+container: "system"
+
+flag {
+ name: "use_sf_frame_duration"
+ namespace: "android_platform_window_surfaces"
+ description: "Whether to get the frame duration from SurfaceFlinger, or HWUI"
+ bug: "354763298"
+ is_fixed_read_only: true
+}
diff --git a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
index 07fa679..dfb2884 100644
--- a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
+++ b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
@@ -18,6 +18,10 @@
import android.os.Parcel;
import android.os.Parcelable;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
+import android.ravenwood.annotation.RavenwoodReplace;
import com.android.internal.util.Preconditions;
@@ -55,18 +59,15 @@
*
* @hide
*/
-@android.ravenwood.annotation.RavenwoodKeepWholeClass
-@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
- "com.android.platform.test.ravenwood.nativesubstitution.LongArrayMultiStateCounter_host")
+@RavenwoodKeepWholeClass
+@RavenwoodRedirectionClass("LongArrayMultiStateCounter_host")
public final class LongArrayMultiStateCounter implements Parcelable {
/**
* Container for a native equivalent of a long[].
*/
- @android.ravenwood.annotation.RavenwoodKeepWholeClass
- @android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
- "com.android.platform.test.ravenwood.nativesubstitution"
- + ".LongArrayMultiStateCounter_host$LongArrayContainer_host")
+ @RavenwoodKeepWholeClass
+ @RavenwoodRedirectionClass("LongArrayContainer_host")
public static class LongArrayContainer {
private static NativeAllocationRegistry sRegistry;
@@ -81,7 +82,7 @@
registerNativeAllocation();
}
- @android.ravenwood.annotation.RavenwoodReplace
+ @RavenwoodReplace
private void registerNativeAllocation() {
if (sRegistry == null) {
synchronized (LongArrayMultiStateCounter.class) {
@@ -140,18 +141,23 @@
}
@CriticalNative
+ @RavenwoodRedirect
private static native long native_init(int length);
@CriticalNative
+ @RavenwoodRedirect
private static native long native_getReleaseFunc();
@FastNative
+ @RavenwoodRedirect
private static native void native_setValues(long nativeObject, long[] array);
@FastNative
+ @RavenwoodRedirect
private static native void native_getValues(long nativeObject, long[] array);
@FastNative
+ @RavenwoodRedirect
private static native boolean native_combineValues(long nativeObject, long[] array,
int[] indexMap);
}
@@ -175,7 +181,7 @@
registerNativeAllocation();
}
- @android.ravenwood.annotation.RavenwoodReplace
+ @RavenwoodReplace
private void registerNativeAllocation() {
if (sRegistry == null) {
synchronized (LongArrayMultiStateCounter.class) {
@@ -374,57 +380,73 @@
@CriticalNative
+ @RavenwoodRedirect
private static native long native_init(int stateCount, int arrayLength);
@CriticalNative
+ @RavenwoodRedirect
private static native long native_getReleaseFunc();
@CriticalNative
+ @RavenwoodRedirect
private static native void native_setEnabled(long nativeObject, boolean enabled,
long timestampMs);
@CriticalNative
+ @RavenwoodRedirect
private static native void native_setState(long nativeObject, int state, long timestampMs);
@CriticalNative
+ @RavenwoodRedirect
private static native void native_copyStatesFrom(long nativeObjectTarget,
long nativeObjectSource);
@CriticalNative
+ @RavenwoodRedirect
private static native void native_setValues(long nativeObject, int state,
long longArrayContainerNativeObject);
@CriticalNative
+ @RavenwoodRedirect
private static native void native_updateValues(long nativeObject,
long longArrayContainerNativeObject, long timestampMs);
@CriticalNative
+ @RavenwoodRedirect
private static native void native_incrementValues(long nativeObject,
long longArrayContainerNativeObject, long timestampMs);
@CriticalNative
+ @RavenwoodRedirect
private static native void native_addCounts(long nativeObject,
long longArrayContainerNativeObject);
@CriticalNative
+ @RavenwoodRedirect
private static native void native_reset(long nativeObject);
@CriticalNative
+ @RavenwoodRedirect
private static native void native_getCounts(long nativeObject,
long longArrayContainerNativeObject, int state);
@FastNative
+ @RavenwoodRedirect
private static native String native_toString(long nativeObject);
@FastNative
+ @RavenwoodRedirect
private static native void native_writeToParcel(long nativeObject, Parcel dest, int flags);
@FastNative
+ @RavenwoodRedirect
private static native long native_initFromParcel(Parcel parcel);
@CriticalNative
+ @RavenwoodRedirect
private static native int native_getStateCount(long nativeObject);
@CriticalNative
+ @RavenwoodRedirect
private static native int native_getArrayLength(long nativeObject);
}
diff --git a/core/java/com/android/internal/os/LongMultiStateCounter.java b/core/java/com/android/internal/os/LongMultiStateCounter.java
index e5662c7..c386a86 100644
--- a/core/java/com/android/internal/os/LongMultiStateCounter.java
+++ b/core/java/com/android/internal/os/LongMultiStateCounter.java
@@ -18,6 +18,10 @@
import android.os.Parcel;
import android.os.Parcelable;
+import android.ravenwood.annotation.RavenwoodKeepWholeClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
+import android.ravenwood.annotation.RavenwoodReplace;
import com.android.internal.util.Preconditions;
@@ -55,9 +59,8 @@
*
* @hide
*/
-@android.ravenwood.annotation.RavenwoodKeepWholeClass
-@android.ravenwood.annotation.RavenwoodNativeSubstitutionClass(
- "com.android.platform.test.ravenwood.nativesubstitution.LongMultiStateCounter_host")
+@RavenwoodKeepWholeClass
+@RavenwoodRedirectionClass("LongMultiStateCounter_host")
public final class LongMultiStateCounter implements Parcelable {
private static NativeAllocationRegistry sRegistry;
@@ -82,7 +85,7 @@
mStateCount = native_getStateCount(mNativeObject);
}
- @android.ravenwood.annotation.RavenwoodReplace
+ @RavenwoodReplace
private void registerNativeAllocation() {
if (sRegistry == null) {
synchronized (LongMultiStateCounter.class) {
@@ -210,43 +213,56 @@
@CriticalNative
+ @RavenwoodRedirect
private static native long native_init(int stateCount);
@CriticalNative
+ @RavenwoodRedirect
private static native long native_getReleaseFunc();
@CriticalNative
+ @RavenwoodRedirect
private static native void native_setEnabled(long nativeObject, boolean enabled,
long timestampMs);
@CriticalNative
+ @RavenwoodRedirect
private static native void native_setState(long nativeObject, int state, long timestampMs);
@CriticalNative
+ @RavenwoodRedirect
private static native long native_updateValue(long nativeObject, long value, long timestampMs);
@CriticalNative
+ @RavenwoodRedirect
private static native void native_incrementValue(long nativeObject, long increment,
long timestampMs);
@CriticalNative
+ @RavenwoodRedirect
private static native void native_addCount(long nativeObject, long count);
@CriticalNative
+ @RavenwoodRedirect
private static native void native_reset(long nativeObject);
@CriticalNative
+ @RavenwoodRedirect
private static native long native_getCount(long nativeObject, int state);
@FastNative
+ @RavenwoodRedirect
private static native String native_toString(long nativeObject);
@FastNative
+ @RavenwoodRedirect
private static native void native_writeToParcel(long nativeObject, Parcel dest, int flags);
@FastNative
+ @RavenwoodRedirect
private static native long native_initFromParcel(Parcel parcel);
@CriticalNative
+ @RavenwoodRedirect
private static native int native_getStateCount(long nativeObject);
}
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index cdac097..1709ca7 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -404,6 +404,17 @@
}
public static void redirectLogStreams$ravenwood() {
+ if (sOut$ravenwood != null && sErr$ravenwood != null) {
+ return; // Already initialized.
+ }
+
+ // Make sure the Log class is loaded and the JNI methods are hooked up,
+ // before redirecting System.out/err.
+ // Otherwise, because ClassLoadHook tries to write to System.out, this would cause
+ // a circular initialization problem and would cause a UnsatisfiedLinkError
+ // on the JNI methods.
+ Log.isLoggable("X", Log.VERBOSE);
+
if (sOut$ravenwood == null) {
sOut$ravenwood = System.out;
System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
diff --git a/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java b/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java
index 12d3264..032ac42 100644
--- a/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java
+++ b/core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java
@@ -3025,6 +3025,7 @@
@Override
public PackageImpl setSplitCodePaths(@Nullable String[] splitCodePaths) {
this.splitCodePaths = splitCodePaths;
+ this.mSplits = null; // reset for paths changed
if (splitCodePaths != null) {
int size = splitCodePaths.length;
for (int index = 0; index < size; index++) {
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 4828393..4708be8 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -63,6 +63,9 @@
import android.graphics.drawable.Drawable;
import android.graphics.drawable.InsetDrawable;
import android.graphics.drawable.LayerDrawable;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.Looper;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Pair;
@@ -114,6 +117,7 @@
import com.android.window.flags.Flags;
import java.util.List;
+import java.util.concurrent.Executor;
import java.util.function.Consumer;
/** @hide */
@@ -1140,7 +1144,8 @@
mDrawLegacyNavigationBarBackground =
((requestedVisibleTypes | mLastForceConsumingTypes)
& WindowInsets.Type.navigationBars()) != 0
- && (mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0;
+ && (mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
+ && navBarSize > 0;
if (oldDrawLegacy != mDrawLegacyNavigationBarBackground) {
mDrawLegacyNavigationBarBackgroundHandled =
mWindow.onDrawLegacyNavigationBarBackgroundChanged(
@@ -1348,8 +1353,15 @@
mCrossWindowBlurEnabled = enabled;
updateBackgroundBlurRadius();
};
+ // The executor to receive callback {@link mCrossWindowBlurEnabledListener}. It
+ // should be the executor for this {@link DecorView}'s ui thread (not necessarily
+ // the main thread).
+ final Executor executor = Looper.myLooper() == Looper.getMainLooper()
+ ? getContext().getMainExecutor()
+ : new HandlerExecutor(new Handler(Looper.myLooper()));
getContext().getSystemService(WindowManager.class)
- .addCrossWindowBlurEnabledListener(mCrossWindowBlurEnabledListener);
+ .addCrossWindowBlurEnabledListener(
+ executor, mCrossWindowBlurEnabledListener);
getViewTreeObserver().addOnPreDrawListener(mBackgroundBlurOnPreDrawListener);
} else {
updateBackgroundBlurRadius();
diff --git a/core/java/com/android/internal/policy/TransitionAnimation.java b/core/java/com/android/internal/policy/TransitionAnimation.java
index 201f267..238e6f5 100644
--- a/core/java/com/android/internal/policy/TransitionAnimation.java
+++ b/core/java/com/android/internal/policy/TransitionAnimation.java
@@ -49,7 +49,7 @@
import android.media.Image;
import android.media.ImageReader;
import android.os.Handler;
-import android.os.UserHandle;
+import android.os.SystemProperties;
import android.util.Slog;
import android.view.InflateException;
import android.view.SurfaceControl;
@@ -187,44 +187,23 @@
return createHiddenByKeyguardExit(mContext, mInterpolator, onWallpaper, toShade, subtle);
}
- /** Load keyguard unocclude animation for user. */
- @Nullable
- public Animation loadKeyguardUnoccludeAnimation(int userId) {
- return loadDefaultAnimationRes(com.android.internal.R.anim.wallpaper_open_exit, userId);
- }
-
- /** Same as {@code loadKeyguardUnoccludeAnimation} for current user. */
@Nullable
public Animation loadKeyguardUnoccludeAnimation() {
- return loadKeyguardUnoccludeAnimation(UserHandle.USER_CURRENT);
+ return loadDefaultAnimationRes(com.android.internal.R.anim.wallpaper_open_exit);
}
- /** Load voice activity open animation for user. */
- @Nullable
- public Animation loadVoiceActivityOpenAnimation(boolean enter, int userId) {
- return loadDefaultAnimationRes(enter
- ? com.android.internal.R.anim.voice_activity_open_enter
- : com.android.internal.R.anim.voice_activity_open_exit, userId);
- }
-
- /** Same as {@code loadVoiceActivityOpenAnimation} for current user. */
@Nullable
public Animation loadVoiceActivityOpenAnimation(boolean enter) {
- return loadVoiceActivityOpenAnimation(enter, UserHandle.USER_CURRENT);
- }
-
- /** Load voice activity exit animation for user. */
- @Nullable
- public Animation loadVoiceActivityExitAnimation(boolean enter, int userId) {
return loadDefaultAnimationRes(enter
- ? com.android.internal.R.anim.voice_activity_close_enter
- : com.android.internal.R.anim.voice_activity_close_exit, userId);
+ ? com.android.internal.R.anim.voice_activity_open_enter
+ : com.android.internal.R.anim.voice_activity_open_exit);
}
- /** Same as {@code loadVoiceActivityExitAnimation} for current user. */
@Nullable
public Animation loadVoiceActivityExitAnimation(boolean enter) {
- return loadVoiceActivityExitAnimation(enter, UserHandle.USER_CURRENT);
+ return loadDefaultAnimationRes(enter
+ ? com.android.internal.R.anim.voice_activity_close_enter
+ : com.android.internal.R.anim.voice_activity_close_exit);
}
@Nullable
@@ -232,17 +211,10 @@
return loadAnimationRes(packageName, resId);
}
- /** Load cross profile app enter animation for user. */
- @Nullable
- public Animation loadCrossProfileAppEnterAnimation(int userId) {
- return loadAnimationRes(DEFAULT_PACKAGE,
- com.android.internal.R.anim.task_open_enter_cross_profile_apps, userId);
- }
-
- /** Same as {@code loadCrossProfileAppEnterAnimation} for current user. */
@Nullable
public Animation loadCrossProfileAppEnterAnimation() {
- return loadCrossProfileAppEnterAnimation(UserHandle.USER_CURRENT);
+ return loadAnimationRes(DEFAULT_PACKAGE,
+ com.android.internal.R.anim.task_open_enter_cross_profile_apps);
}
@Nullable
@@ -258,11 +230,11 @@
appRect.height(), 0, null);
}
- /** Load animation by resource Id from specific package for user. */
+ /** Load animation by resource Id from specific package. */
@Nullable
- public Animation loadAnimationRes(String packageName, int resId, int userId) {
+ public Animation loadAnimationRes(String packageName, int resId) {
if (ResourceId.isValid(resId)) {
- AttributeCache.Entry ent = getCachedAnimations(packageName, resId, userId);
+ AttributeCache.Entry ent = getCachedAnimations(packageName, resId);
if (ent != null) {
return loadAnimationSafely(ent.context, resId, mTag);
}
@@ -270,22 +242,10 @@
return null;
}
- /** Same as {@code loadAnimationRes} for current user. */
- @Nullable
- public Animation loadAnimationRes(String packageName, int resId) {
- return loadAnimationRes(packageName, resId, UserHandle.USER_CURRENT);
- }
-
- /** Load animation by resource Id from android package for user. */
- @Nullable
- public Animation loadDefaultAnimationRes(int resId, int userId) {
- return loadAnimationRes(DEFAULT_PACKAGE, resId, userId);
- }
-
- /** Same as {@code loadDefaultAnimationRes} for current user. */
+ /** Load animation by resource Id from android package. */
@Nullable
public Animation loadDefaultAnimationRes(int resId) {
- return loadAnimationRes(DEFAULT_PACKAGE, resId, UserHandle.USER_CURRENT);
+ return loadAnimationRes(DEFAULT_PACKAGE, resId);
}
/** Load animation by attribute Id from specific LayoutParams */
@@ -418,10 +378,10 @@
}
@Nullable
- private AttributeCache.Entry getCachedAnimations(String packageName, int resId, int userId) {
+ private AttributeCache.Entry getCachedAnimations(String packageName, int resId) {
if (mDebug) {
- Slog.v(mTag, "Loading animations: package=" + packageName + " resId=0x"
- + Integer.toHexString(resId) + " for user=" + userId);
+ Slog.v(mTag, "Loading animations: package="
+ + packageName + " resId=0x" + Integer.toHexString(resId));
}
if (packageName != null) {
if ((resId & 0xFF000000) == 0x01000000) {
@@ -432,16 +392,11 @@
+ packageName);
}
return AttributeCache.instance().get(packageName, resId,
- com.android.internal.R.styleable.WindowAnimation, userId);
+ com.android.internal.R.styleable.WindowAnimation);
}
return null;
}
- @Nullable
- private AttributeCache.Entry getCachedAnimations(String packageName, int resId) {
- return getCachedAnimations(packageName, resId, UserHandle.USER_CURRENT);
- }
-
/** Returns window animation style ID from {@link LayoutParams} or from system in some cases */
public int getAnimationStyleResId(@NonNull LayoutParams lp) {
int resId = lp.windowAnimations;
diff --git a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
index 4264358..e440dc9 100644
--- a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
@@ -34,7 +34,6 @@
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.LOCATION;
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;
@@ -72,7 +71,6 @@
import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
@@ -99,13 +97,11 @@
public static final String NULL_STRING = "null";
private final AtomicInteger mTracingInstances = new AtomicInteger();
- private final ProtoLogDataSource mDataSource = new ProtoLogDataSource(
- this::onTracingInstanceStart,
- this::onTracingFlush,
- this::onTracingInstanceStop
- );
+ @NonNull
+ private final ProtoLogDataSource mDataSource;
@Nullable
private final ProtoLogViewerConfigReader mViewerConfigReader;
+ @Deprecated
@Nullable
private final ViewerConfigInputStreamProvider mViewerConfigInputStreamProvider;
@NonNull
@@ -151,13 +147,29 @@
cacheUpdater, groups);
}
+ @Deprecated
@VisibleForTesting
public PerfettoProtoLogImpl(
@Nullable ViewerConfigInputStreamProvider viewerConfigInputStreamProvider,
@Nullable ProtoLogViewerConfigReader viewerConfigReader,
@NonNull Runnable cacheUpdater,
- @NonNull IProtoLogGroup[] groups) {
- this(null, viewerConfigInputStreamProvider, viewerConfigReader, cacheUpdater, groups);
+ @NonNull IProtoLogGroup[] groups,
+ @NonNull ProtoLogDataSourceBuilder dataSourceBuilder,
+ @NonNull ProtoLogConfigurationService configurationService) {
+ this(null, viewerConfigInputStreamProvider, viewerConfigReader, cacheUpdater,
+ groups, dataSourceBuilder, configurationService);
+ }
+
+ @VisibleForTesting
+ public PerfettoProtoLogImpl(
+ @Nullable String viewerConfigFilePath,
+ @Nullable ProtoLogViewerConfigReader viewerConfigReader,
+ @NonNull Runnable cacheUpdater,
+ @NonNull IProtoLogGroup[] groups,
+ @NonNull ProtoLogDataSourceBuilder dataSourceBuilder,
+ @NonNull ProtoLogConfigurationService configurationService) {
+ this(viewerConfigFilePath, null, viewerConfigReader, cacheUpdater,
+ groups, dataSourceBuilder, configurationService);
}
private PerfettoProtoLogImpl(
@@ -166,11 +178,31 @@
@Nullable ProtoLogViewerConfigReader viewerConfigReader,
@NonNull Runnable cacheUpdater,
@NonNull IProtoLogGroup[] groups) {
+ this(viewerConfigFilePath, viewerConfigInputStreamProvider, viewerConfigReader,
+ cacheUpdater, groups,
+ ProtoLogDataSource::new,
+ IProtoLogConfigurationService.Stub
+ .asInterface(ServiceManager.getService(PROTOLOG_CONFIGURATION_SERVICE))
+ );
+ }
+
+ private PerfettoProtoLogImpl(
+ @Nullable String viewerConfigFilePath,
+ @Nullable ViewerConfigInputStreamProvider viewerConfigInputStreamProvider,
+ @Nullable ProtoLogViewerConfigReader viewerConfigReader,
+ @NonNull Runnable cacheUpdater,
+ @NonNull IProtoLogGroup[] groups,
+ @NonNull ProtoLogDataSourceBuilder dataSourceBuilder,
+ @Nullable IProtoLogConfigurationService configurationService) {
if (viewerConfigFilePath != null && viewerConfigInputStreamProvider != null) {
throw new RuntimeException("Only one of viewerConfigFilePath and "
+ "viewerConfigInputStreamProvider can be set");
}
+ mDataSource = dataSourceBuilder.build(
+ this::onTracingInstanceStart,
+ this::onTracingFlush,
+ this::onTracingInstanceStop);
Producer.init(InitArguments.DEFAULTS);
DataSourceParams params =
new DataSourceParams.Builder()
@@ -186,9 +218,7 @@
registerGroupsLocally(groups);
if (android.tracing.Flags.clientSideProtoLogging()) {
- mProtoLogConfigurationService =
- IProtoLogConfigurationService.Stub.asInterface(ServiceManager.getService(
- PROTOLOG_CONFIGURATION_SERVICE));
+ mProtoLogConfigurationService = configurationService;
Objects.requireNonNull(mProtoLogConfigurationService,
"ServiceManager returned a null ProtoLog Configuration Service");
@@ -431,6 +461,7 @@
Log.d(LOG_TAG, "Finished onTracingFlush");
}
+ @Deprecated
private void dumpViewerConfig() {
if (mViewerConfigInputStreamProvider == null) {
// No viewer config available
@@ -439,103 +470,29 @@
Log.d(LOG_TAG, "Dumping viewer config to trace");
- mDataSource.trace(ctx -> {
- try {
- ProtoInputStream pis = mViewerConfigInputStreamProvider.getInputStream();
-
- final ProtoOutputStream os = ctx.newTracePacket();
-
- os.write(TIMESTAMP, SystemClock.elapsedRealtimeNanos());
-
- final long outProtologViewerConfigToken = os.start(PROTOLOG_VIEWER_CONFIG);
- while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
- if (pis.getFieldNumber() == (int) MESSAGES) {
- writeViewerConfigMessage(pis, os);
- }
-
- if (pis.getFieldNumber() == (int) GROUPS) {
- writeViewerConfigGroup(pis, os);
- }
- }
-
- os.end(outProtologViewerConfigToken);
- } catch (IOException e) {
- Log.e(LOG_TAG, "Failed to read ProtoLog viewer config to dump on tracing end", e);
- }
- });
+ Utils.dumpViewerConfig(mDataSource, mViewerConfigInputStreamProvider);
Log.d(LOG_TAG, "Dumped viewer config to trace");
}
- private static void writeViewerConfigGroup(
- ProtoInputStream pis, ProtoOutputStream os) throws IOException {
- final long inGroupToken = pis.start(GROUPS);
- final long outGroupToken = os.start(GROUPS);
-
- while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
- switch (pis.getFieldNumber()) {
- case (int) ID:
- int id = pis.readInt(ID);
- os.write(ID, id);
- break;
- case (int) NAME:
- String name = pis.readString(NAME);
- os.write(NAME, name);
- break;
- case (int) TAG:
- String tag = pis.readString(TAG);
- os.write(TAG, tag);
- break;
- default:
- throw new RuntimeException(
- "Unexpected field id " + pis.getFieldNumber());
- }
- }
-
- pis.end(inGroupToken);
- os.end(outGroupToken);
- }
-
- private static void writeViewerConfigMessage(
- ProtoInputStream pis, ProtoOutputStream os) throws IOException {
- final long inMessageToken = pis.start(MESSAGES);
- final long outMessagesToken = os.start(MESSAGES);
-
- while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
- switch (pis.getFieldNumber()) {
- case (int) MessageData.MESSAGE_ID:
- os.write(MessageData.MESSAGE_ID,
- pis.readLong(MessageData.MESSAGE_ID));
- break;
- case (int) MESSAGE:
- os.write(MESSAGE, pis.readString(MESSAGE));
- break;
- case (int) LEVEL:
- os.write(LEVEL, pis.readInt(LEVEL));
- break;
- case (int) GROUP_ID:
- os.write(GROUP_ID, pis.readInt(GROUP_ID));
- break;
- case (int) LOCATION:
- os.write(LOCATION, pis.readString(LOCATION));
- break;
- default:
- throw new RuntimeException(
- "Unexpected field id " + pis.getFieldNumber());
- }
- }
-
- pis.end(inMessageToken);
- os.end(outMessagesToken);
- }
-
private void logToLogcat(String tag, LogLevel level, Message message,
@Nullable Object[] args) {
String messageString;
if (mViewerConfigReader == null) {
messageString = message.getMessage();
+
+ if (messageString == null) {
+ Log.e(LOG_TAG, "Failed to decode message for logcat. "
+ + "Message not available without ViewerConfig to decode the hash.");
+ }
} else {
messageString = message.getMessage(mViewerConfigReader);
+
+ if (messageString == null) {
+ Log.e(LOG_TAG, "Failed to decode message for logcat. "
+ + "Message hash either not available in viewerConfig file or "
+ + "not loaded into memory from file before decoding.");
+ }
}
if (messageString == null) {
@@ -733,12 +690,16 @@
incrementalState.protologMessageInterningSet.add(messageHash);
final ProtoOutputStream os = ctx.newTracePacket();
+
+ // Dependent on the ProtoLog viewer config packet that contains the group information.
+ os.write(SEQUENCE_FLAGS, SEQ_NEEDS_INCREMENTAL_STATE);
+
final long protologViewerConfigToken = os.start(PROTOLOG_VIEWER_CONFIG);
final long messageConfigToken = os.start(MESSAGES);
os.write(MessageData.MESSAGE_ID, messageHash);
os.write(MESSAGE, message);
- os.write(LEVEL, level.ordinal());
+ os.write(LEVEL, level.id);
os.write(GROUP_ID, logGroup.getId());
os.end(messageConfigToken);
@@ -932,8 +893,7 @@
private static class Message {
@Nullable
private final Long mMessageHash;
- @Nullable
- private final Integer mMessageMask;
+ private final int mMessageMask;
@Nullable
private final String mMessageString;
@@ -950,8 +910,7 @@
this.mMessageString = messageString;
}
- @Nullable
- private Integer getMessageMask() {
+ private int getMessageMask() {
return mMessageMask;
}
diff --git a/core/java/com/android/internal/protolog/ProtoLogConfigurationService.java b/core/java/com/android/internal/protolog/ProtoLogConfigurationService.java
index eeac139..7031d69 100644
--- a/core/java/com/android/internal/protolog/ProtoLogConfigurationService.java
+++ b/core/java/com/android/internal/protolog/ProtoLogConfigurationService.java
@@ -26,8 +26,6 @@
import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.LOCATION;
import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE;
import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE_ID;
-import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.PROTOLOG_VIEWER_CONFIG;
-import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.TIMESTAMP;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -36,7 +34,6 @@
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
-import android.os.SystemClock;
import android.tracing.perfetto.DataSourceParams;
import android.tracing.perfetto.InitArguments;
import android.tracing.perfetto.Producer;
@@ -75,11 +72,7 @@
public final class ProtoLogConfigurationService extends IProtoLogConfigurationService.Stub {
private static final String LOG_TAG = "ProtoLogConfigurationService";
- private final ProtoLogDataSource mDataSource = new ProtoLogDataSource(
- this::onTracingInstanceStart,
- this::onTracingInstanceFlush,
- this::onTracingInstanceStop
- );
+ private final ProtoLogDataSource mDataSource;
/**
* Keeps track of how many of each viewer config file is currently registered.
@@ -116,11 +109,29 @@
private final ViewerConfigFileTracer mViewerConfigFileTracer;
public ProtoLogConfigurationService() {
- this(ProtoLogConfigurationService::dumpTransitionTraceConfig);
+ this(ProtoLogDataSource::new, ProtoLogConfigurationService::dumpTransitionTraceConfig);
+ }
+
+ @VisibleForTesting
+ public ProtoLogConfigurationService(@NonNull ProtoLogDataSourceBuilder dataSourceBuilder) {
+ this(dataSourceBuilder, ProtoLogConfigurationService::dumpTransitionTraceConfig);
}
@VisibleForTesting
public ProtoLogConfigurationService(@NonNull ViewerConfigFileTracer tracer) {
+ this(ProtoLogDataSource::new, tracer);
+ }
+
+ @VisibleForTesting
+ public ProtoLogConfigurationService(
+ @NonNull ProtoLogDataSourceBuilder dataSourceBuilder,
+ @NonNull ViewerConfigFileTracer tracer) {
+ mDataSource = dataSourceBuilder.build(
+ this::onTracingInstanceStart,
+ this::onTracingInstanceFlush,
+ this::onTracingInstanceStop
+ );
+
// Initialize the Perfetto producer and register the Perfetto ProtoLog datasource to be
// receive the lifecycle callbacks of the datasource and write the viewer configs if and
// when required to the datasource.
@@ -361,32 +372,13 @@
private static void dumpTransitionTraceConfig(@NonNull ProtoLogDataSource dataSource,
@NonNull String viewerConfigFilePath) {
- dataSource.trace(ctx -> {
- final ProtoInputStream pis;
+ Utils.dumpViewerConfig(dataSource, () -> {
try {
- pis = new ProtoInputStream(new FileInputStream(viewerConfigFilePath));
+ return new ProtoInputStream(new FileInputStream(viewerConfigFilePath));
} catch (FileNotFoundException e) {
throw new RuntimeException(
"Failed to load viewer config file " + viewerConfigFilePath, e);
}
-
- try {
- final ProtoOutputStream os = ctx.newTracePacket();
-
- os.write(TIMESTAMP, SystemClock.elapsedRealtimeNanos());
-
- final long outProtologViewerConfigToken = os.start(PROTOLOG_VIEWER_CONFIG);
- while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
- switch (pis.getFieldNumber()) {
- case (int) MESSAGES -> writeViewerConfigMessage(pis, os);
- case (int) GROUPS -> writeViewerConfigGroup(pis, os);
- }
- }
-
- os.end(outProtologViewerConfigToken);
- } catch (IOException e) {
- Log.e(LOG_TAG, "Failed to read ProtoLog viewer config to dump on tracing end", e);
- }
});
}
diff --git a/core/java/com/android/internal/protolog/ProtoLogDataSource.java b/core/java/com/android/internal/protolog/ProtoLogDataSource.java
index 837622f..0afb135 100644
--- a/core/java/com/android/internal/protolog/ProtoLogDataSource.java
+++ b/core/java/com/android/internal/protolog/ProtoLogDataSource.java
@@ -25,6 +25,7 @@
import static android.internal.perfetto.protos.ProtologConfig.ProtoLogGroup.GROUP_NAME;
import static android.internal.perfetto.protos.ProtologConfig.ProtoLogGroup.LOG_FROM;
+import android.annotation.NonNull;
import android.internal.perfetto.protos.DataSourceConfigOuterClass.DataSourceConfig;
import android.internal.perfetto.protos.ProtologCommon;
import android.tracing.perfetto.CreateIncrementalStateArgs;
@@ -51,18 +52,26 @@
ProtoLogDataSource.IncrementalState> {
private static final String DATASOURCE_NAME = "android.protolog";
+ @NonNull
private final Instance.TracingInstanceStartCallback mOnStart;
+ @NonNull
private final Runnable mOnFlush;
+ @NonNull
private final Instance.TracingInstanceStopCallback mOnStop;
- public ProtoLogDataSource(Instance.TracingInstanceStartCallback onStart, Runnable onFlush,
- Instance.TracingInstanceStopCallback onStop) {
+ public ProtoLogDataSource(
+ @NonNull Instance.TracingInstanceStartCallback onStart,
+ @NonNull Runnable onFlush,
+ @NonNull Instance.TracingInstanceStopCallback onStop) {
this(onStart, onFlush, onStop, DATASOURCE_NAME);
}
@VisibleForTesting
- public ProtoLogDataSource(Instance.TracingInstanceStartCallback onStart, Runnable onFlush,
- Instance.TracingInstanceStopCallback onStop, String dataSourceName) {
+ public ProtoLogDataSource(
+ @NonNull Instance.TracingInstanceStartCallback onStart,
+ @NonNull Runnable onFlush,
+ @NonNull Instance.TracingInstanceStopCallback onStop,
+ @NonNull String dataSourceName) {
super(dataSourceName);
this.mOnStart = onStart;
this.mOnFlush = onFlush;
@@ -70,7 +79,8 @@
}
@Override
- public Instance createInstance(ProtoInputStream configStream, int instanceIndex) {
+ @NonNull
+ public Instance createInstance(@NonNull ProtoInputStream configStream, int instanceIndex) {
ProtoLogConfig config = null;
try {
@@ -100,7 +110,8 @@
}
@Override
- public TlsState createTlsState(CreateTlsStateArgs<Instance> args) {
+ @NonNull
+ public TlsState createTlsState(@NonNull CreateTlsStateArgs<Instance> args) {
try (Instance dsInstance = args.getDataSourceInstanceLocked()) {
if (dsInstance == null) {
// Datasource instance has been removed
@@ -111,14 +122,17 @@
}
@Override
- public IncrementalState createIncrementalState(CreateIncrementalStateArgs<Instance> args) {
+ @NonNull
+ public IncrementalState createIncrementalState(
+ @NonNull CreateIncrementalStateArgs<Instance> args) {
return new IncrementalState();
}
public static class TlsState {
+ @NonNull
private final ProtoLogConfig mConfig;
- private TlsState(ProtoLogConfig config) {
+ private TlsState(@NonNull ProtoLogConfig config) {
this.mConfig = config;
}
@@ -269,26 +283,44 @@
public static class Instance extends DataSourceInstance {
public interface TracingInstanceStartCallback {
- void run(int instanceIdx, ProtoLogConfig config);
+ /**
+ * Execute the tracing instance's onStart callback.
+ * @param instanceIdx The index of the tracing instance we are executing the callback
+ * for.
+ * @param config The protolog configuration for the tracing instance we are executing
+ * the callback for.
+ */
+ void run(int instanceIdx, @NonNull ProtoLogConfig config);
}
public interface TracingInstanceStopCallback {
- void run(int instanceIdx, ProtoLogConfig config);
+ /**
+ * Execute the tracing instance's onStop callback.
+ * @param instanceIdx The index of the tracing instance we are executing the callback
+ * for.
+ * @param config The protolog configuration for the tracing instance we are executing
+ * the callback for.
+ */
+ void run(int instanceIdx, @NonNull ProtoLogConfig config);
}
+ @NonNull
private final TracingInstanceStartCallback mOnStart;
+ @NonNull
private final Runnable mOnFlush;
+ @NonNull
private final TracingInstanceStopCallback mOnStop;
+ @NonNull
private final ProtoLogConfig mConfig;
private final int mInstanceIndex;
public Instance(
- DataSource<Instance, TlsState, IncrementalState> dataSource,
+ @NonNull DataSource<Instance, TlsState, IncrementalState> dataSource,
int instanceIdx,
- ProtoLogConfig config,
- TracingInstanceStartCallback onStart,
- Runnable onFlush,
- TracingInstanceStopCallback onStop
+ @NonNull ProtoLogConfig config,
+ @NonNull TracingInstanceStartCallback onStart,
+ @NonNull Runnable onFlush,
+ @NonNull TracingInstanceStopCallback onStop
) {
super(dataSource, instanceIdx);
this.mInstanceIndex = instanceIdx;
diff --git a/core/java/com/android/internal/protolog/ProtoLogDataSourceBuilder.java b/core/java/com/android/internal/protolog/ProtoLogDataSourceBuilder.java
new file mode 100644
index 0000000..da78b62
--- /dev/null
+++ b/core/java/com/android/internal/protolog/ProtoLogDataSourceBuilder.java
@@ -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.internal.protolog;
+
+import android.annotation.NonNull;
+
+public interface ProtoLogDataSourceBuilder {
+ /**
+ * Builder method for the DataSource the PerfettoProtoLogImpl is going to us.
+ * @param onStart The onStart callback that should be used by the created datasource.
+ * @param onFlush The onFlush callback that should be used by the created datasource.
+ * @param onStop The onStop callback that should be used by the created datasource.
+ * @return A new DataSource that uses the provided callbacks.
+ */
+ @NonNull
+ ProtoLogDataSource build(
+ @NonNull ProtoLogDataSource.Instance.TracingInstanceStartCallback onStart,
+ @NonNull Runnable onFlush,
+ @NonNull ProtoLogDataSource.Instance.TracingInstanceStopCallback onStop);
+}
diff --git a/core/java/com/android/internal/protolog/ProtoLogImpl.java b/core/java/com/android/internal/protolog/ProtoLogImpl.java
index da6d8cf..7bdcf2d 100644
--- a/core/java/com/android/internal/protolog/ProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/ProtoLogImpl.java
@@ -23,6 +23,7 @@
import static com.android.internal.protolog.common.ProtoLogToolInjected.Value.VIEWER_CONFIG_PATH;
import android.annotation.Nullable;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.IProtoLog;
@@ -37,6 +38,8 @@
* A service for the ProtoLog logging system.
*/
public class ProtoLogImpl {
+ private static final String LOG_TAG = "ProtoLogImpl";
+
private static IProtoLog sServiceInstance = null;
@ProtoLogToolInjected(VIEWER_CONFIG_PATH)
@@ -97,6 +100,9 @@
*/
public static synchronized IProtoLog getSingleInstance() {
if (sServiceInstance == null) {
+ Log.i(LOG_TAG, "Setting up " + ProtoLogImpl.class.getSimpleName() + " with "
+ + "viewerConfigPath = " + sViewerConfigPath);
+
final var groups = sLogGroups.values().toArray(new IProtoLogGroup[0]);
if (android.tracing.Flags.perfettoProtologTracing()) {
@@ -105,6 +111,9 @@
// TODO(b/353530422): Remove - temporary fix to unblock b/352290057
// In some tests the viewer config file might not exist in which we don't
// want to provide config path to the user
+ Log.w(LOG_TAG, "Failed to find viewerConfigFile when setting up "
+ + ProtoLogImpl.class.getSimpleName() + ". "
+ + "Setting up without a viewer config instead...");
sServiceInstance = new PerfettoProtoLogImpl(sCacheUpdater, groups);
} else {
sServiceInstance =
diff --git a/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
index 3b24f27..0a80e00 100644
--- a/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
+++ b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
@@ -24,7 +24,9 @@
public class ProtoLogViewerConfigReader {
@NonNull
private final ViewerConfigInputStreamProvider mViewerConfigInputStreamProvider;
+ @NonNull
private final Map<String, Set<Long>> mGroupHashes = new TreeMap<>();
+ @NonNull
private final LongSparseArray<String> mLogMessageMap = new LongSparseArray<>();
public ProtoLogViewerConfigReader(
@@ -41,14 +43,21 @@
return mLogMessageMap.get(messageHash);
}
- public synchronized void loadViewerConfig(String[] groups) {
+ /**
+ * Load the viewer configs for the target groups into memory.
+ * Only viewer configs loaded into memory can be required. So this must be called for all groups
+ * we want to query before we query their viewer config.
+ *
+ * @param groups Groups to load the viewer configs from file into memory.
+ */
+ public synchronized void loadViewerConfig(@NonNull String[] groups) {
loadViewerConfig(groups, (message) -> {});
}
/**
* Loads the viewer config into memory. No-op if already loaded in memory.
*/
- public synchronized void loadViewerConfig(String[] groups, @NonNull ILogger logger) {
+ public synchronized void loadViewerConfig(@NonNull String[] groups, @NonNull ILogger logger) {
for (String group : groups) {
if (mGroupHashes.containsKey(group)) {
continue;
@@ -69,14 +78,14 @@
}
}
- public synchronized void unloadViewerConfig(String[] groups) {
+ public synchronized void unloadViewerConfig(@NonNull String[] groups) {
unloadViewerConfig(groups, (message) -> {});
}
/**
* Unload the viewer config from memory.
*/
- public synchronized void unloadViewerConfig(String[] groups, @NonNull ILogger logger) {
+ public synchronized void unloadViewerConfig(@NonNull String[] groups, @NonNull ILogger logger) {
for (String group : groups) {
if (!mGroupHashes.containsKey(group)) {
continue;
@@ -90,8 +99,10 @@
}
}
- private Map<Long, String> loadViewerConfigMappingForGroup(String group) throws IOException {
- Long targetGroupId = loadGroupId(group);
+ @NonNull
+ private Map<Long, String> loadViewerConfigMappingForGroup(@NonNull String group)
+ throws IOException {
+ long targetGroupId = loadGroupId(group);
final Map<Long, String> hashesForGroup = new TreeMap<>();
final ProtoInputStream pis = mViewerConfigInputStreamProvider.getInputStream();
@@ -140,7 +151,7 @@
return hashesForGroup;
}
- private Long loadGroupId(String group) throws IOException {
+ private long loadGroupId(@NonNull String group) throws IOException {
final ProtoInputStream pis = mViewerConfigInputStreamProvider.getInputStream();
while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
diff --git a/core/java/com/android/internal/protolog/Utils.java b/core/java/com/android/internal/protolog/Utils.java
new file mode 100644
index 0000000..1e6ba30
--- /dev/null
+++ b/core/java/com/android/internal/protolog/Utils.java
@@ -0,0 +1,138 @@
+/*
+ * 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.protolog;
+
+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.LOCATION;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.PROTOLOG_VIEWER_CONFIG;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.TIMESTAMP;
+
+import android.annotation.NonNull;
+import android.internal.perfetto.protos.Protolog;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.proto.ProtoInputStream;
+import android.util.proto.ProtoOutputStream;
+
+import java.io.IOException;
+
+public class Utils {
+ private static final String LOG_TAG = "ProtoLogUtils";
+
+ /**
+ * Dump the viewer config provided by the input stream to the target datasource.
+ * @param dataSource The datasource to dump the ProtoLog viewer config to.
+ * @param viewerConfigInputStreamProvider The InputStream that provided the proto viewer config.
+ */
+ public static void dumpViewerConfig(@NonNull ProtoLogDataSource dataSource,
+ @NonNull ViewerConfigInputStreamProvider viewerConfigInputStreamProvider) {
+ dataSource.trace(ctx -> {
+ try {
+ ProtoInputStream pis = viewerConfigInputStreamProvider.getInputStream();
+
+ final ProtoOutputStream os = ctx.newTracePacket();
+
+ os.write(TIMESTAMP, SystemClock.elapsedRealtimeNanos());
+
+ final long outProtologViewerConfigToken = os.start(PROTOLOG_VIEWER_CONFIG);
+ while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+ if (pis.getFieldNumber() == (int) MESSAGES) {
+ writeViewerConfigMessage(pis, os);
+ }
+
+ if (pis.getFieldNumber() == (int) GROUPS) {
+ writeViewerConfigGroup(pis, os);
+ }
+ }
+
+ os.end(outProtologViewerConfigToken);
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "Failed to read ProtoLog viewer config to dump to datasource", e);
+ }
+ });
+ }
+
+ private static void writeViewerConfigGroup(
+ @NonNull ProtoInputStream pis, @NonNull ProtoOutputStream os) throws IOException {
+ final long inGroupToken = pis.start(GROUPS);
+ final long outGroupToken = os.start(GROUPS);
+
+ while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+ switch (pis.getFieldNumber()) {
+ case (int) ID:
+ int id = pis.readInt(ID);
+ os.write(ID, id);
+ break;
+ case (int) NAME:
+ String name = pis.readString(NAME);
+ os.write(NAME, name);
+ break;
+ case (int) TAG:
+ String tag = pis.readString(TAG);
+ os.write(TAG, tag);
+ break;
+ default:
+ throw new RuntimeException(
+ "Unexpected field id " + pis.getFieldNumber());
+ }
+ }
+
+ pis.end(inGroupToken);
+ os.end(outGroupToken);
+ }
+
+ private static void writeViewerConfigMessage(
+ ProtoInputStream pis, ProtoOutputStream os) throws IOException {
+ final long inMessageToken = pis.start(MESSAGES);
+ final long outMessagesToken = os.start(MESSAGES);
+
+ while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+ switch (pis.getFieldNumber()) {
+ case (int) Protolog.ProtoLogViewerConfig.MessageData.MESSAGE_ID:
+ os.write(Protolog.ProtoLogViewerConfig.MessageData.MESSAGE_ID,
+ pis.readLong(Protolog.ProtoLogViewerConfig.MessageData.MESSAGE_ID));
+ break;
+ case (int) MESSAGE:
+ os.write(MESSAGE, pis.readString(MESSAGE));
+ break;
+ case (int) LEVEL:
+ os.write(LEVEL, pis.readInt(LEVEL));
+ break;
+ case (int) GROUP_ID:
+ os.write(GROUP_ID, pis.readInt(GROUP_ID));
+ break;
+ case (int) LOCATION:
+ os.write(LOCATION, pis.readString(LOCATION));
+ break;
+ default:
+ throw new RuntimeException(
+ "Unexpected field id " + pis.getFieldNumber());
+ }
+ }
+
+ pis.end(inMessageToken);
+ os.end(outMessagesToken);
+ }
+
+}
diff --git a/core/java/com/android/internal/protolog/common/LogLevel.java b/core/java/com/android/internal/protolog/common/LogLevel.java
index 16c34e1..b5541ae 100644
--- a/core/java/com/android/internal/protolog/common/LogLevel.java
+++ b/core/java/com/android/internal/protolog/common/LogLevel.java
@@ -17,10 +17,18 @@
package com.android.internal.protolog.common;
public enum LogLevel {
- DEBUG("d"), VERBOSE("v"), INFO("i"), WARN("w"), ERROR("e"), WTF("wtf");
+ DEBUG("d", 1),
+ VERBOSE("v", 2),
+ INFO("i", 3),
+ WARN("w", 4),
+ ERROR("e", 5),
+ WTF("wtf", 6);
public final String shortCode;
- LogLevel(String shortCode) {
+ public final int id;
+
+ LogLevel(String shortCode, int id) {
this.shortCode = shortCode;
+ this.id = id;
}
}
diff --git a/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java b/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java
index ee3a3c2..30b160a 100644
--- a/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java
+++ b/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java
@@ -16,15 +16,15 @@
package com.android.internal.ravenwood;
import android.ravenwood.annotation.RavenwoodKeepWholeClass;
-import android.ravenwood.annotation.RavenwoodNativeSubstitutionClass;
+import android.ravenwood.annotation.RavenwoodRedirect;
+import android.ravenwood.annotation.RavenwoodRedirectionClass;
import android.ravenwood.annotation.RavenwoodReplace;
/**
* Class to interact with the Ravenwood environment.
*/
@RavenwoodKeepWholeClass
-@RavenwoodNativeSubstitutionClass(
- "com.android.platform.test.ravenwood.nativesubstitution.RavenwoodEnvironment_host")
+@RavenwoodRedirectionClass("RavenwoodEnvironment_host")
public final class RavenwoodEnvironment {
public static final String TAG = "RavenwoodEnvironment";
@@ -40,7 +40,7 @@
ensureRavenwoodInitialized();
}
- private static RuntimeException notSupportedOnDevice() {
+ public static RuntimeException notSupportedOnDevice() {
return new UnsupportedOperationException("This method can only be used on Ravenwood");
}
@@ -56,12 +56,10 @@
*
* No-op if called on the device side.
*/
- @RavenwoodReplace
+ @RavenwoodRedirect
public static void ensureRavenwoodInitialized() {
}
- private static native void ensureRavenwoodInitialized$ravenwood();
-
/**
* USE IT SPARINGLY! Returns true if it's running on Ravenwood, hostside test environment.
*
@@ -87,13 +85,11 @@
* Get the object back from the address obtained from
* {@link dalvik.system.VMRuntime#addressOf(Object)}.
*/
- @RavenwoodReplace
+ @RavenwoodRedirect
public <T> T fromAddress(long address) {
throw notSupportedOnDevice();
}
- private native <T> T fromAddress$ravenwood(long address);
-
/**
* See {@link Workaround}. It's only usable on Ravenwood.
*/
@@ -109,13 +105,11 @@
/**
* @return the "ravenwood-runtime" directory.
*/
- @RavenwoodReplace
+ @RavenwoodRedirect
public String getRavenwoodRuntimePath() {
throw notSupportedOnDevice();
}
- private native String getRavenwoodRuntimePath$ravenwood();
-
/**
* A set of APIs used to work around missing features on Ravenwood. Ideally, this class should
* be empty, and all its APIs should be able to be implemented properly.
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 11c220b..0ec55f9 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -120,6 +120,7 @@
private static final String TAG = "LockPatternView";
private OnPatternListener mOnPatternListener;
+ private ExternalHapticsPlayer mExternalHapticsPlayer;
@UnsupportedAppUsage
private final ArrayList<Cell> mPattern = new ArrayList<Cell>(9);
@@ -317,6 +318,13 @@
void onPatternDetected(List<Cell> pattern);
}
+ /** An external haptics player for pattern updates. */
+ public interface ExternalHapticsPlayer{
+
+ /** Perform haptic feedback when a cell is added to the pattern. */
+ void performCellAddedFeedback();
+ }
+
public LockPatternView(Context context) {
this(context, null);
}
@@ -461,6 +469,15 @@
}
/**
+ * Set the external haptics player for feedback on pattern detection.
+ * @param player The external player.
+ */
+ @UnsupportedAppUsage
+ public void setExternalHapticsPlayer(ExternalHapticsPlayer player) {
+ mExternalHapticsPlayer = player;
+ }
+
+ /**
* Set the pattern explicitely (rather than waiting for the user to input
* a pattern).
* @param displayMode How to display the pattern.
@@ -847,6 +864,16 @@
return null;
}
+ @Override
+ public boolean performHapticFeedback(int feedbackConstant, int flags) {
+ if (mExternalHapticsPlayer != null) {
+ mExternalHapticsPlayer.performCellAddedFeedback();
+ return true;
+ } else {
+ return super.performHapticFeedback(feedbackConstant, flags);
+ }
+ }
+
private void addCellToPattern(Cell newCell) {
mPatternDrawLookup[newCell.getRow()][newCell.getColumn()] = true;
mPattern.add(newCell);
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 46710b5..9bccf5a 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -3379,44 +3379,39 @@
public:
JavaSystemPropertyListener(JNIEnv* env, jobject javaCallback, std::string sysPropName) :
mCallback {javaCallback, env},
- mPi {__system_property_find(sysPropName.c_str())},
+ mSysPropName(sysPropName),
+ mCachedProperty(android::base::CachedProperty{std::move(sysPropName)}),
mListenerThread([this](mediautils::stop_token stok) mutable {
- static const struct timespec close_delay = { .tv_sec = 1 };
while (!stok.stop_requested()) {
- uint32_t old_serial = mSerial.load();
- uint32_t new_serial;
- if (__system_property_wait(mPi, old_serial, &new_serial, &close_delay)) {
- while (new_serial > old_serial) {
- if (mSerial.compare_exchange_weak(old_serial, new_serial)) {
- fireUpdate();
- break;
- }
- }
- }
+ using namespace std::chrono_literals;
+ // 1s timeout so this thread can eventually respond to the stop token
+ std::string newVal = mCachedProperty.WaitForChange(1000ms) ?: "";
+ updateValue(newVal);
}
}) {}
void triggerUpdateIfChanged() {
- uint32_t old_serial = mSerial.load();
- uint32_t new_serial = __system_property_serial(mPi);
- while (new_serial > old_serial) {
- if (mSerial.compare_exchange_weak(old_serial, new_serial)) {
- fireUpdate();
- break;
- }
- }
+ // We must check the property without using the cached property due to thread safety issues
+ std::string newVal = base::GetProperty(mSysPropName, "");
+ updateValue(newVal);
}
private:
- void fireUpdate() {
+ void updateValue(std::string newVal) {
+ if (newVal == "") return;
+ std::lock_guard l{mLock};
+ if (mLastVal == newVal) return;
const auto threadEnv = GetOrAttachJNIEnvironment(gVm);
threadEnv->CallVoidMethod(mCallback.get(), gRunnableClassInfo.run);
+ mLastVal = std::move(newVal);
}
// Should outlive thread object
const GlobalRef mCallback;
- const prop_info * const mPi;
- std::atomic<uint32_t> mSerial = 0;
+ const std::string mSysPropName;
+ android::base::CachedProperty mCachedProperty;
+ std::string mLastVal = "";
+ std::mutex mLock;
const mediautils::jthread mListenerThread;
};
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 46b4695..921b77d 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -56,11 +56,11 @@
//#undef ALOGV
//#define ALOGV(...) fprintf(stderr, __VA_ARGS__)
-#define DEBUG_DEATH 0
-#if DEBUG_DEATH
-#define LOGDEATH ALOGD
+#define DEBUG_DEATH_FREEZE 0
+#if DEBUG_DEATH_FREEZE
+#define LOG_DEATH_FREEZE ALOGD
#else
-#define LOGDEATH ALOGV
+#define LOG_DEATH_FREEZE ALOGV
#endif
using namespace android;
@@ -116,6 +116,7 @@
jclass mClass;
jmethodID mGetInstance;
jmethodID mSendDeathNotice;
+ jmethodID mInvokeFrozenStateChangeCallback;
// Object state.
jfieldID mNativeData; // Field holds native pointer to BinderProxyNativeData.
@@ -547,23 +548,59 @@
// ----------------------------------------------------------------------------
-// Per-IBinder death recipient bookkeeping. This is how we reconcile local jobject
-// death recipient references passed in through JNI with the permanent corresponding
-// JavaDeathRecipient objects.
+// A JavaRecipient receives either death notifications or frozen state change
+// callbacks from natve code (IBinder) and dispatch the notifications to its
+// corresponding Java listener object.
+//
+// A RecipientList keeps tracks of all JavaRecipients for an IBinder. This way
+// we can find a JavaRecipient given a Java listener object.
+//
+// The implementation is shared between death recipients and frozen state change
+// callbacks via template. For death recipients the template is instantiated as
+// follows:
+//
+// IBinder::DeathRecipient
+// ^
+// |
+// (inherits)
+// |
+// JavaRecipient<IBinder::DeathRecipient> <----> RecipientList<IBinder::DeathRecipient>
+// ^
+// |
+// (inherits)
+// |
+// JavaDeathRecipient
+//
+//
+// The instantiation for frozen state change callbacks are:
+//
+// IBinder::FrozenStateChangeCallback
+// ^
+// |
+// (inherits)
+// |
+// JavaRecipient<IBinder::FrozenStateChangeCallback>
+// ^ ^
+// | |
+// (inherits) +--> RecipientList<IBinder::FrozenStateChangeCallback>
+// |
+// JavaFrozenStateChangeCallback
-class JavaDeathRecipient;
+template <typename T>
+class JavaRecipient;
-class DeathRecipientList : public RefBase {
- List< sp<JavaDeathRecipient> > mList;
+template <typename T>
+class RecipientList : public RefBase {
+ List<sp<JavaRecipient<T> > > mList;
Mutex mLock;
public:
- DeathRecipientList();
- ~DeathRecipientList();
+ RecipientList();
+ ~RecipientList();
- void add(const sp<JavaDeathRecipient>& recipient);
- void remove(const sp<JavaDeathRecipient>& recipient);
- sp<JavaDeathRecipient> find(jobject recipient);
+ void add(const sp<JavaRecipient<T> >& recipient);
+ void remove(const sp<JavaRecipient<T> >& recipient);
+ sp<JavaRecipient<T> > find(jobject recipient);
Mutex& lock(); // Use with care; specifically for mutual exclusion during binder death
};
@@ -584,11 +621,113 @@
#endif // __BIONIC__
#endif // BINDER_DEATH_RECIPIENT_WEAK_FROM_JNI
-class JavaDeathRecipient : public IBinder::DeathRecipient
-{
+template <typename T>
+constexpr const char* logPrefix();
+
+template <>
+constexpr const char* logPrefix<IBinder::DeathRecipient>() {
+ return "[DEATH]";
+}
+
+template <>
+constexpr const char* logPrefix<IBinder::FrozenStateChangeCallback>() {
+ return "[FREEZE]";
+}
+
+template <typename T>
+class JavaRecipient : public T {
public:
- JavaDeathRecipient(JNIEnv* env, jobject object, const sp<DeathRecipientList>& list)
+ JavaRecipient(JNIEnv* env, jobject object, const sp<RecipientList<T> >& list,
+ bool useWeakReference)
: mVM(jnienv_to_javavm(env)), mObject(NULL), mObjectWeak(NULL), mList(list) {
+ if (useWeakReference) {
+ mObjectWeak = env->NewWeakGlobalRef(object);
+ } else {
+ mObject = env->NewGlobalRef(object);
+ }
+ // These objects manage their own lifetimes so are responsible for final bookkeeping.
+ // The list holds a strong reference to this object.
+ LOG_DEATH_FREEZE("%s Adding JavaRecipient %p to RecipientList %p", logPrefix<T>(), this,
+ list.get());
+ list->add(this);
+ }
+
+ void clearReference() {
+ sp<RecipientList<T> > list = mList.promote();
+ if (list != NULL) {
+ LOG_DEATH_FREEZE("%s Removing JavaRecipient %p from RecipientList %p", logPrefix<T>(),
+ this, list.get());
+ list->remove(this);
+ } else {
+ LOG_DEATH_FREEZE("%s clearReference() on JavaRecipient %p but RecipientList wp purged",
+ logPrefix<T>(), this);
+ }
+ }
+
+ bool matches(jobject obj) {
+ bool result;
+ JNIEnv* env = javavm_to_jnienv(mVM);
+
+ if (mObject != NULL) {
+ result = env->IsSameObject(obj, mObject);
+ } else {
+ ScopedLocalRef<jobject> me(env, env->NewLocalRef(mObjectWeak));
+ result = env->IsSameObject(obj, me.get());
+ }
+ return result;
+ }
+
+ void warnIfStillLive() {
+ if (mObject != NULL) {
+ // Okay, something is wrong -- we have a hard reference to a live death
+ // recipient on the VM side, but the list is being torn down.
+ JNIEnv* env = javavm_to_jnienv(mVM);
+ ScopedLocalRef<jclass> objClassRef(env, env->GetObjectClass(mObject));
+ ScopedLocalRef<jstring> nameRef(env,
+ (jstring)env->CallObjectMethod(objClassRef.get(),
+ gClassOffsets.mGetName));
+ ScopedUtfChars nameUtf(env, nameRef.get());
+ if (nameUtf.c_str() != NULL) {
+ ALOGW("BinderProxy is being destroyed but the application did not call "
+ "unlinkToDeath to unlink all of its death recipients beforehand. "
+ "Releasing leaked death recipient: %s",
+ nameUtf.c_str());
+ } else {
+ ALOGW("BinderProxy being destroyed; unable to get DR object name");
+ env->ExceptionClear();
+ }
+ }
+ }
+
+protected:
+ virtual ~JavaRecipient() {
+ // ALOGI("Removing death ref: recipient=%p\n", mObject);
+ JNIEnv* env = javavm_to_jnienv(mVM);
+ if (mObject != NULL) {
+ env->DeleteGlobalRef(mObject);
+ } else {
+ env->DeleteWeakGlobalRef(mObjectWeak);
+ }
+ }
+
+ JavaVM* const mVM;
+
+ // If useWeakReference is false (e.g. JavaDeathRecipient when target sdk version < 35), the
+ // Java-side Recipient is strongly referenced from mObject initially, and may later be demoted
+ // to a weak reference (mObjectWeak), e.g. upon linkToDeath() and then after binderDied() is
+ // called.
+ // If useWeakReference is true, the strong reference is never made here (i.e. mObject == NULL
+ // always). Instead, the strong reference to the Java-side Recipient is made in
+ // BinderProxy.{mDeathRecipients,mFrozenStateChangeCallbacks}. In the native world, only the
+ // weak reference is kept.
+ jobject mObject;
+ jweak mObjectWeak;
+ wp<RecipientList<T> > mList;
+};
+
+class JavaDeathRecipient : public JavaRecipient<IBinder::DeathRecipient> {
+public:
+ static bool useWeakReference() {
// b/298374304: For apps targeting Android V or beyond, we no longer hold the global JNI ref
// to the death recipient objects. This is to prevent the memory leak which can happen when
// the death recipient object internally has a strong reference to the proxy object. Under
@@ -604,25 +743,26 @@
// reference to. If however you want to get binderDied() regardless of the proxy object's
// lifecycle, keep a strong reference to the death recipient object by yourself.
#ifdef BINDER_DEATH_RECIPIENT_WEAK_FROM_JNI
- if (target_sdk_is_at_least_vic()) {
- mObjectWeak = env->NewWeakGlobalRef(object);
- } else
+ return target_sdk_is_at_least_vic();
+#else
+ return false;
#endif
- {
- mObject = env->NewGlobalRef(object);
- }
- // These objects manage their own lifetimes so are responsible for final bookkeeping.
- // The list holds a strong reference to this object.
- LOGDEATH("Adding JDR %p to DRL %p", this, list.get());
- list->add(this);
+ }
+ JavaDeathRecipient(JNIEnv* env, jobject object,
+ const sp<RecipientList<IBinder::DeathRecipient> >& list)
+ : JavaRecipient(env, object, list, useWeakReference()) {
gNumDeathRefsCreated.fetch_add(1, std::memory_order_relaxed);
gcIfManyNewRefs(env);
}
+ ~JavaDeathRecipient() {
+ gNumDeathRefsDeleted.fetch_add(1, std::memory_order_relaxed);
+ }
+
void binderDied(const wp<IBinder>& who)
{
- LOGDEATH("Receiving binderDied() on JavaDeathRecipient %p\n", this);
+ LOG_DEATH_FREEZE("Receiving binderDied() on JavaDeathRecipient %p\n", this);
if (mObject == NULL && mObjectWeak == NULL) {
return;
}
@@ -662,7 +802,7 @@
// with our containing DeathRecipientList so that we can't delete the global ref on mObject
// while the list is being iterated.
if (mObject != NULL) {
- sp<DeathRecipientList> list = mList.promote();
+ auto list = mList.promote();
if (list != NULL) {
AutoMutex _l(list->lock());
@@ -673,126 +813,96 @@
}
}
- void clearReference()
- {
- sp<DeathRecipientList> list = mList.promote();
- if (list != NULL) {
- LOGDEATH("Removing JDR %p from DRL %p", this, list.get());
- list->remove(this);
- } else {
- LOGDEATH("clearReference() on JDR %p but DRL wp purged", this);
- }
- }
-
- bool matches(jobject obj) {
- bool result;
- JNIEnv* env = javavm_to_jnienv(mVM);
-
- if (mObject != NULL) {
- result = env->IsSameObject(obj, mObject);
- } else {
- ScopedLocalRef<jobject> me(env, env->NewLocalRef(mObjectWeak));
- result = env->IsSameObject(obj, me.get());
- }
- return result;
- }
-
- void warnIfStillLive() {
- if (mObject != NULL) {
- // Okay, something is wrong -- we have a hard reference to a live death
- // recipient on the VM side, but the list is being torn down.
- JNIEnv* env = javavm_to_jnienv(mVM);
- ScopedLocalRef<jclass> objClassRef(env, env->GetObjectClass(mObject));
- ScopedLocalRef<jstring> nameRef(env,
- (jstring) env->CallObjectMethod(objClassRef.get(), gClassOffsets.mGetName));
- ScopedUtfChars nameUtf(env, nameRef.get());
- if (nameUtf.c_str() != NULL) {
- ALOGW("BinderProxy is being destroyed but the application did not call "
- "unlinkToDeath to unlink all of its death recipients beforehand. "
- "Releasing leaked death recipient: %s", nameUtf.c_str());
- } else {
- ALOGW("BinderProxy being destroyed; unable to get DR object name");
- env->ExceptionClear();
- }
- }
- }
-
-protected:
- virtual ~JavaDeathRecipient()
- {
- //ALOGI("Removing death ref: recipient=%p\n", mObject);
- gNumDeathRefsDeleted.fetch_add(1, std::memory_order_relaxed);
- JNIEnv* env = javavm_to_jnienv(mVM);
- if (mObject != NULL) {
- env->DeleteGlobalRef(mObject);
- } else {
- env->DeleteWeakGlobalRef(mObjectWeak);
- }
- }
-
private:
- JavaVM* const mVM;
-
- // If target sdk version < 35, the Java-side DeathRecipient is strongly referenced from mObject
- // upon linkToDeath() and then after binderDied() is called, the strong reference is demoted to
- // a weak reference (mObjectWeak).
- // If target sdk version >= 35, the strong reference is never made here (i.e. mObject == NULL
- // always). Instead, the strong reference to the Java-side DeathRecipient is made in
- // BinderProxy.mDeathRecipients. In the native world, only the weak reference is kept.
- jobject mObject;
- jweak mObjectWeak;
- wp<DeathRecipientList> mList;
-
// Whether binderDied was called or not.
bool mFired = false;
};
+class JavaFrozenStateChangeCallback : public JavaRecipient<IBinder::FrozenStateChangeCallback> {
+public:
+ JavaFrozenStateChangeCallback(
+ JNIEnv* env, jobject object,
+ const sp<RecipientList<IBinder::FrozenStateChangeCallback> >& list)
+ : JavaRecipient(env, object, list, /*useWeakReference=*/true) {}
+
+ void onStateChanged(const wp<IBinder>& who, State state) {
+ LOG_DEATH_FREEZE("Receiving onStateChanged() on JavaFrozenStateChangeCallback %p. state: "
+ "%s\n",
+ this, state == State::FROZEN ? "FROZEN" : "UNFROZEN");
+ if (mObjectWeak == NULL) {
+ return;
+ }
+ JNIEnv* env = javavm_to_jnienv(mVM);
+ ScopedLocalRef<jobject> jBinderProxy(env, javaObjectForIBinder(env, who.promote()));
+
+ // Hold a local reference to the recipient. This may fail if the recipient is weakly
+ // referenced, in which case we can't deliver the notification.
+ ScopedLocalRef<jobject> jCallback(env, env->NewLocalRef(mObjectWeak));
+ if (jCallback.get() == NULL) {
+ return;
+ }
+ env->CallStaticVoidMethod(gBinderProxyOffsets.mClass,
+ gBinderProxyOffsets.mInvokeFrozenStateChangeCallback,
+ jCallback.get(), jBinderProxy.get(), state);
+ if (env->ExceptionCheck()) {
+ jthrowable excep = env->ExceptionOccurred();
+ binder_report_exception(env, excep,
+ "*** Uncaught exception returned from frozen state change "
+ "notification!");
+ }
+ }
+};
+
// ----------------------------------------------------------------------------
-DeathRecipientList::DeathRecipientList() {
- LOGDEATH("New DRL @ %p", this);
+template <typename T>
+RecipientList<T>::RecipientList() {
+ LOG_DEATH_FREEZE("%s New RecipientList @ %p", logPrefix<T>(), this);
}
-DeathRecipientList::~DeathRecipientList() {
- LOGDEATH("Destroy DRL @ %p", this);
+template <typename T>
+RecipientList<T>::~RecipientList() {
+ LOG_DEATH_FREEZE("%s Destroy RecipientList @ %p", logPrefix<T>(), this);
AutoMutex _l(mLock);
- // Should never happen -- the JavaDeathRecipient objects that have added themselves
+ // Should never happen -- the JavaRecipientList objects that have added themselves
// to the list are holding references on the list object. Only when they are torn
// down can the list header be destroyed.
if (mList.size() > 0) {
- List< sp<JavaDeathRecipient> >::iterator iter;
- for (iter = mList.begin(); iter != mList.end(); iter++) {
+ for (auto iter = mList.begin(); iter != mList.end(); iter++) {
(*iter)->warnIfStillLive();
}
}
}
-void DeathRecipientList::add(const sp<JavaDeathRecipient>& recipient) {
+template <typename T>
+void RecipientList<T>::add(const sp<JavaRecipient<T> >& recipient) {
AutoMutex _l(mLock);
- LOGDEATH("DRL @ %p : add JDR %p", this, recipient.get());
+ LOG_DEATH_FREEZE("%s RecipientList @ %p : add JavaRecipient %p", logPrefix<T>(), this,
+ recipient.get());
mList.push_back(recipient);
}
-void DeathRecipientList::remove(const sp<JavaDeathRecipient>& recipient) {
+template <typename T>
+void RecipientList<T>::remove(const sp<JavaRecipient<T> >& recipient) {
AutoMutex _l(mLock);
- List< sp<JavaDeathRecipient> >::iterator iter;
- for (iter = mList.begin(); iter != mList.end(); iter++) {
+ for (auto iter = mList.begin(); iter != mList.end(); iter++) {
if (*iter == recipient) {
- LOGDEATH("DRL @ %p : remove JDR %p", this, recipient.get());
+ LOG_DEATH_FREEZE("%s RecipientList @ %p : remove JavaRecipient %p", logPrefix<T>(),
+ this, recipient.get());
mList.erase(iter);
return;
}
}
}
-sp<JavaDeathRecipient> DeathRecipientList::find(jobject recipient) {
+template <typename T>
+sp<JavaRecipient<T> > RecipientList<T>::find(jobject recipient) {
AutoMutex _l(mLock);
- List< sp<JavaDeathRecipient> >::iterator iter;
- for (iter = mList.begin(); iter != mList.end(); iter++) {
+ for (auto iter = mList.begin(); iter != mList.end(); iter++) {
if ((*iter)->matches(recipient)) {
return *iter;
}
@@ -800,10 +910,14 @@
return NULL;
}
-Mutex& DeathRecipientList::lock() {
+template <typename T>
+Mutex& RecipientList<T>::lock() {
return mLock;
}
+using DeathRecipientList = RecipientList<IBinder::DeathRecipient>;
+using FrozenStateChangeCallbackList = RecipientList<IBinder::FrozenStateChangeCallback>;
+
// ----------------------------------------------------------------------------
namespace android {
@@ -821,6 +935,11 @@
// Death recipients for mObject. Reference counted only because DeathRecipients
// hold a weak reference that can be temporarily promoted.
sp<DeathRecipientList> mOrgue; // Death recipients for mObject.
+
+ // Frozen state change callbacks for mObject. Reference counted only because
+ // JavaFrozenStateChangeCallback hold a weak reference that can be
+ // temporarily promoted.
+ sp<FrozenStateChangeCallbackList> mFrozenStateChangCallbackList;
};
BinderProxyNativeData* getBPNativeData(JNIEnv* env, jobject obj) {
@@ -840,12 +959,13 @@
if (val->checkSubclass(&gBinderOffsets)) {
// It's a JavaBBinder created by ibinderForJavaObject. Already has Java object.
jobject object = static_cast<JavaBBinder*>(val.get())->object();
- LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
+ LOG_DEATH_FREEZE("objectForBinder %p: it's our own %p!\n", val.get(), object);
return object;
}
BinderProxyNativeData* nativeData = new BinderProxyNativeData();
nativeData->mOrgue = new DeathRecipientList;
+ nativeData->mFrozenStateChangCallbackList = new FrozenStateChangeCallbackList;
nativeData->mObject = val;
jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
@@ -1448,7 +1568,7 @@
BinderProxyNativeData *nd = getBPNativeData(env, obj);
IBinder* target = nd->mObject.get();
- LOGDEATH("linkToDeath: binder=%p recipient=%p\n", target, recipient);
+ LOG_DEATH_FREEZE("linkToDeath: binder=%p recipient=%p\n", target, recipient);
if (!target->localBinder()) {
DeathRecipientList* list = nd->mOrgue.get();
@@ -1479,15 +1599,15 @@
return JNI_FALSE;
}
- LOGDEATH("unlinkToDeath: binder=%p recipient=%p\n", target, recipient);
+ LOG_DEATH_FREEZE("unlinkToDeath: binder=%p recipient=%p\n", target, recipient);
if (!target->localBinder()) {
status_t err = NAME_NOT_FOUND;
// If we find the matching recipient, proceed to unlink using that
DeathRecipientList* list = nd->mOrgue.get();
- sp<JavaDeathRecipient> origJDR = list->find(recipient);
- LOGDEATH(" unlink found list %p and JDR %p", list, origJDR.get());
+ sp<JavaRecipient<IBinder::DeathRecipient> > origJDR = list->find(recipient);
+ LOG_DEATH_FREEZE(" unlink found list %p and JDR %p", list, origJDR.get());
if (origJDR != NULL) {
wp<IBinder::DeathRecipient> dr;
err = target->unlinkToDeath(origJDR, NULL, flags, &dr);
@@ -1513,11 +1633,85 @@
return res;
}
+static void android_os_BinderProxy_addFrozenStateChangeCallback(
+ JNIEnv* env, jobject obj,
+ jobject callback) // throws RemoteException
+{
+ if (callback == NULL) {
+ jniThrowNullPointerException(env, NULL);
+ return;
+ }
+
+ BinderProxyNativeData* nd = getBPNativeData(env, obj);
+ IBinder* target = nd->mObject.get();
+
+ LOG_DEATH_FREEZE("addFrozenStateChangeCallback: binder=%p callback=%p\n", target, callback);
+
+ if (!target->localBinder()) {
+ FrozenStateChangeCallbackList* list = nd->mFrozenStateChangCallbackList.get();
+ auto jfscc = sp<JavaFrozenStateChangeCallback>::make(env, callback, list);
+ status_t err = target->addFrozenStateChangeCallback(jfscc);
+ if (err != NO_ERROR) {
+ // Failure adding the callback, so clear its reference now.
+ jfscc->clearReference();
+ signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
+ }
+ }
+}
+
+static jboolean android_os_BinderProxy_removeFrozenStateChangeCallback(JNIEnv* env, jobject obj,
+ jobject callback) {
+ jboolean res = JNI_FALSE;
+ if (callback == NULL) {
+ jniThrowNullPointerException(env, NULL);
+ return res;
+ }
+
+ BinderProxyNativeData* nd = getBPNativeData(env, obj);
+ IBinder* target = nd->mObject.get();
+ if (target == NULL) {
+ ALOGW("Binder has been finalized when calling removeFrozenStateChangeCallback() with "
+ "callback=%p)\n",
+ callback);
+ return JNI_FALSE;
+ }
+
+ LOG_DEATH_FREEZE("removeFrozenStateChangeCallback: binder=%p callback=%p\n", target, callback);
+
+ if (!target->localBinder()) {
+ status_t err = NAME_NOT_FOUND;
+
+ // If we find the matching callback, proceed to unlink using that
+ FrozenStateChangeCallbackList* list = nd->mFrozenStateChangCallbackList.get();
+ sp<JavaRecipient<IBinder::FrozenStateChangeCallback> > origJFSCC = list->find(callback);
+ LOG_DEATH_FREEZE(" removeFrozenStateChangeCallback found list %p and JFSCC %p", list,
+ origJFSCC.get());
+ if (origJFSCC != NULL) {
+ err = target->removeFrozenStateChangeCallback(origJFSCC);
+ if (err == NO_ERROR) {
+ origJFSCC->clearReference();
+ }
+ }
+
+ if (err == NO_ERROR || err == DEAD_OBJECT) {
+ res = JNI_TRUE;
+ } else {
+ jniThrowException(env, "java/util/NoSuchElementException",
+ base::StringPrintf("Frozen state change callback does not exist (%s)",
+ statusToString(err).c_str())
+ .c_str());
+ }
+ }
+
+ return res;
+}
+
static void BinderProxy_destroy(void* rawNativeData)
{
BinderProxyNativeData * nativeData = (BinderProxyNativeData *) rawNativeData;
- LOGDEATH("Destroying BinderProxy: binder=%p drl=%p\n",
- nativeData->mObject.get(), nativeData->mOrgue.get());
+ LOG_DEATH_FREEZE("Destroying BinderProxy: binder=%p drl=%p fsccl=%p\n",
+ nativeData->mObject.get(), nativeData->mOrgue.get(),
+ nativeData->mFrozenStateChangCallbackList.get());
delete nativeData;
IPCThreadState::self()->flushCommands();
}
@@ -1552,6 +1746,10 @@
{"transactNative", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
{"linkToDeathNative", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
{"unlinkToDeathNative", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
+ {"addFrozenStateChangeCallbackNative",
+ "(Landroid/os/IBinder$IFrozenStateChangeCallback;)V", (void*)android_os_BinderProxy_addFrozenStateChangeCallback},
+ {"removeFrozenStateChangeCallbackNative",
+ "(Landroid/os/IBinder$IFrozenStateChangeCallback;)Z", (void*)android_os_BinderProxy_removeFrozenStateChangeCallback},
{"getNativeFinalizer", "()J", (void*)android_os_BinderProxy_getNativeFinalizer},
{"getExtension", "()Landroid/os/IBinder;", (void*)android_os_BinderProxy_getExtension},
};
@@ -1574,6 +1772,10 @@
gBinderProxyOffsets.mSendDeathNotice =
GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
"(Landroid/os/IBinder$DeathRecipient;Landroid/os/IBinder;)V");
+ gBinderProxyOffsets.mInvokeFrozenStateChangeCallback =
+ GetStaticMethodIDOrDie(env, clazz, "invokeFrozenStateChangeCallback",
+ "(Landroid/os/IBinder$IFrozenStateChangeCallback;Landroid/os/"
+ "IBinder;I)V");
gBinderProxyOffsets.mNativeData = GetFieldIDOrDie(env, clazz, "mNativeData", "J");
clazz = FindClassOrDie(env, "java/lang/Class");
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 0f53164..17c89f8 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -2089,9 +2089,11 @@
jobjectArray jJankDataArray = env->NewObjectArray(jankData.size(),
gJankDataClassInfo.clazz, nullptr);
for (size_t i = 0; i < jankData.size(); i++) {
- jobject jJankData = env->NewObject(gJankDataClassInfo.clazz, gJankDataClassInfo.ctor,
- jankData[i].frameVsyncId, jankData[i].jankType,
- jankData[i].frameIntervalNs);
+ jobject jJankData =
+ env->NewObject(gJankDataClassInfo.clazz, gJankDataClassInfo.ctor,
+ jankData[i].frameVsyncId, jankData[i].jankType,
+ jankData[i].frameIntervalNs, jankData[i].scheduledAppFrameTimeNs,
+ jankData[i].actualAppFrameTimeNs);
env->SetObjectArrayElement(jJankDataArray, i, jJankData);
env->DeleteLocalRef(jJankData);
}
@@ -2727,7 +2729,7 @@
jclass jankDataClazz =
FindClassOrDie(env, "android/view/SurfaceControl$JankData");
gJankDataClassInfo.clazz = MakeGlobalRefOrDie(env, jankDataClazz);
- gJankDataClassInfo.ctor = GetMethodIDOrDie(env, gJankDataClassInfo.clazz, "<init>", "(JIJ)V");
+ gJankDataClassInfo.ctor = GetMethodIDOrDie(env, gJankDataClassInfo.clazz, "<init>", "(JIJJJ)V");
jclass onJankDataListenerClazz =
FindClassOrDie(env, "android/view/SurfaceControl$OnJankDataListener");
gJankDataListenerClassInfo.clazz = MakeGlobalRefOrDie(env, onJankDataListenerClazz);
diff --git a/core/jni/android_view_TunnelModeEnabledListener.cpp b/core/jni/android_view_TunnelModeEnabledListener.cpp
index af7bae8..d9ab957 100644
--- a/core/jni/android_view_TunnelModeEnabledListener.cpp
+++ b/core/jni/android_view_TunnelModeEnabledListener.cpp
@@ -88,20 +88,19 @@
void nativeRegister(JNIEnv* env, jclass clazz, jlong ptr) {
sp<TunnelModeEnabledListener> listener = reinterpret_cast<TunnelModeEnabledListener*>(ptr);
- if (SurfaceComposerClient::addTunnelModeEnabledListener(listener) != OK) {
- constexpr auto error_msg = "Couldn't addTunnelModeEnabledListener";
- ALOGE(error_msg);
- jniThrowRuntimeException(env, error_msg);
+ status_t status = SurfaceComposerClient::addTunnelModeEnabledListener(listener);
+ if (status != OK) {
+ ALOGE("Couldn't addTunnelModeEnabledListener (%d)", status);
+ jniThrowRuntimeException(env, "Couldn't addTunnelModeEnabledListener");
}
}
void nativeUnregister(JNIEnv* env, jclass clazz, jlong ptr) {
sp<TunnelModeEnabledListener> listener = reinterpret_cast<TunnelModeEnabledListener*>(ptr);
-
- if (SurfaceComposerClient::removeTunnelModeEnabledListener(listener) != OK) {
- constexpr auto error_msg = "Couldn't removeTunnelModeEnabledListener";
- ALOGE(error_msg);
- jniThrowRuntimeException(env, error_msg);
+ status_t status = SurfaceComposerClient::removeTunnelModeEnabledListener(listener);
+ if (status != OK) {
+ ALOGE("Couldn't removeTunnelModeEnabledListener (%d)", status);
+ jniThrowRuntimeException(env, "Couldn't removeTunnelModeEnabledListener");
}
}
diff --git a/core/res/Android.bp b/core/res/Android.bp
index bcc0a97..17d7bfa 100644
--- a/core/res/Android.bp
+++ b/core/res/Android.bp
@@ -167,6 +167,7 @@
"android.os.flags-aconfig",
"android.os.vibrator.flags-aconfig",
"android.media.tv.flags-aconfig",
+ "com.android.hardware.input.input-aconfig",
],
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5decf7f..d35c66e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4033,7 +4033,6 @@
<!-- Allows an application to manage policy related to block package uninstallation.
<p>Protection level: internal|role
<p>Intended for use by the DEVICE_POLICY_MANAGEMENT role only.
- @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled")
-->
<permission android:name="android.permission.MANAGE_DEVICE_POLICY_BLOCK_UNINSTALL"
android:protectionLevel="internal|role" />
@@ -4041,7 +4040,6 @@
<!-- Allows an application to manage policy related to camera toggle.
<p>Protection level: internal|role
<p>Intended for use by the DEVICE_POLICY_MANAGEMENT role only.
- @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled")
-->
<permission android:name="android.permission.MANAGE_DEVICE_POLICY_CAMERA_TOGGLE"
android:protectionLevel="internal|role" />
@@ -4049,7 +4047,6 @@
<!-- Allows an application to manage policy related to microphone toggle.
<p>Protection level: internal|role
<p>Intended for use by the DEVICE_POLICY_MANAGEMENT role only.
- @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled")
-->
<permission android:name="android.permission.MANAGE_DEVICE_POLICY_MICROPHONE_TOGGLE"
android:protectionLevel="internal|role" />
@@ -8171,7 +8168,8 @@
<p>Not for use by third-party applications.
@hide -->
<permission android:name="android.permission.MANAGE_KEY_GESTURES"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature"
+ android:featureFlag="com.android.hardware.input.manage_key_gestures" />
<uses-permission android:name="android.permission.HANDLE_QUERY_PACKAGE_RESTART" />
diff --git a/core/res/res/drawable/ic_zen_priority_modes.xml b/core/res/res/drawable/ic_zen_priority_modes.xml
index e8691fc..9c72f51 100644
--- a/core/res/res/drawable/ic_zen_priority_modes.xml
+++ b/core/res/res/drawable/ic_zen_priority_modes.xml
@@ -19,7 +19,7 @@
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?android:attr/colorControlNormal">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M480,720Q580,720 650,650Q720,580 720,480Q720,380 650,310Q580,240 480,240L480,480L310,650Q345,683 388.5,701.5Q432,720 480,720ZM480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880ZM480,800Q614,800 707,707Q800,614 800,480Q800,346 707,253Q614,160 480,160Q346,160 253,253Q160,346 160,480Q160,614 253,707Q346,800 480,800ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z"/>
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M280,520L680,520L680,440L280,440L280,520ZM480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880ZM480,800Q614,800 707,707Q800,614 800,480Q800,346 707,253Q614,160 480,160Q346,160 253,253Q160,346 160,480Q160,614 253,707Q346,800 480,800ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z" />
</vector>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 381111c..a1dea82 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"’n App verberg die toestemmingversoek en jou antwoord kan dus nie geverifieer word nie."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tik op \'n kenmerk om dit te begin gebruik:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Kies kenmerke om saam met die toeganklikheidknoppie te gebruik"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Kies kenmerke om saam met die volumesleutelkortpad te gebruik"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> is afgeskakel"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Wysig kortpaaie"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Klaar"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index aa7dcec..2873785 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"አንድ መተግበሪያ የፍቃድ ጥያቄውን እያደበዘዘ ነው ስለዚህ የእርስዎ ምላሽ ሊረጋገጥ አይችልም።"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"አንድ ባህሪን መጠቀም ለመጀመር መታ ያድርጉት፦"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"በተደራሽነት አዝራር የሚጠቀሙባቸው ባሕሪያት ይምረጡ"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"በድምጽ ቁልፍ አቋራጭ የሚጠቀሙባቸው ባሕሪያት ይምረጡ"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ጠፍቷል"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"አቋራጮችን አርትዕ ያድርጉ"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ተከናውኗል"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 4f03ff3..7f02576 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1750,7 +1750,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"تعذَّر التحقّق من ردّك بسبب حجب أحد التطبيقات طلب الحصول على الإذن."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"انقر على ميزة لبدء استخدامها:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"اختيار الميزات التي تريد استخدامها مع زر أدوات تمكين الوصول"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"اختيار الميزات التي تريد استخدامها مع اختصار مفتاح التحكّم في مستوى الصوت"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"تم إيقاف <xliff:g id="SERVICE_NAME">%s</xliff:g>."</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"تعديل الاختصارات"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"تم"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 8c9cda9..bc1dba27 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"এটা এপে অনুমতিৰ অনুৰোধটো অস্পষ্ট কৰি আছে আৰু সেয়েহে আপোনাৰ সঁহাৰিটো সত্যাপন কৰিব নোৱাৰি।"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"কোনো এটা সুবিধা ব্যৱহাৰ কৰিবলৈ সেইটোত টিপক:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"সাধ্য-সুবিধা বুটামটোৰ জৰিয়তে ব্যৱহাৰ কৰিবলৈ সুবিধাসমূহ বাছনি কৰক"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ভলিউম কীৰ শ্বৰ্টকাটটোৰ জৰিয়তে ব্যৱহাৰ কৰিবলৈ সুবিধাসমূহ বাছনি কৰক"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> বন্ধ কৰা হৈছে"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"শ্বৰ্টকাটসমূহ সম্পাদনা কৰক"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"কৰা হ’ল"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index afbe715..e93a57b 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Bir tətbiq icazə sorğusunu gizlətdiyi üçün cavabı yoxlamaq mümkün deyil."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Funksiyanı istifadə etmək üçün onun üzərinə toxunun:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Xüsusi imkanlar düyməsinin köməyilə işə salınacaq funksiyaları seçin"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Səs səviyyəsi düyməsinin qısayolu ilə istifadə edəcəyiniz funksiyaları seçin"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> deaktiv edilib"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Qısayolları redaktə edin"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Hazırdır"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index a20775d..b83eca5 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1747,7 +1747,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikacija krije zahtev za dozvolu, pa odgovor ne može da se verifikuje."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Dodirnite neku funkciju da biste počeli da je koristite:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Odaberite funkcije koje ćete koristiti sa dugmetom Pristupačnost"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Odaberite funkcije za prečicu tasterom jačine zvuka"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Usluga <xliff:g id="SERVICE_NAME">%s</xliff:g> je isključena"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Izmenite prečice"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gotovo"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 871f8d4..59645706 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1748,7 +1748,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Праграма хавае запыт дазволу, таму ваш адказ немагчыма спраўдзіць."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Каб пачаць выкарыстоўваць функцыю, націсніце на яе:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Выберыце функцыі, якія будзеце выкарыстоўваць з кнопкай спецыяльных магчымасцей"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Выберыце функцыі для выкарыстання з клавішай гучнасці"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Сэрвіс \"<xliff:g id="SERVICE_NAME">%s</xliff:g>\" выключаны"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Змяніць ярлыкі"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Гатова"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index c22325c..b6fad9e 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Отговорът ви не може да бъде потвърден, тъй като приложение прикрива заявката за разрешение."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Докоснете дадена функция, за да започнете да я използвате:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Избиране на функции, които да използвате с бутона за достъпност"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Избиране на функции, които да използвате с прекия път чрез бутона за силата на звука"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Изключихте <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Редактиране на преките пътища"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Готово"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 776714c..c434fe9 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"কোনও অ্যাপ অনুমতির অনুরোধ আড়াল করছে তাই আপনার উত্তর যাচাই করা যাবে না।"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"কোনও ফিচার ব্যবহার করা শুরু করতে, সেটিতে ট্যাপ করুন:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"অ্যাক্সেসিবিলিটি বোতামের সাহায্যে আপনি যেসব ফিচার ব্যবহার করতে চান সেগুলি বেছে নিন"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ভলিউম কী শর্টকাটের সাহায্যে আপনি যেসব ফিচার ব্যবহার করতে চান সেগুলি বেছে নিন"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> বন্ধ করে দেওয়া হয়েছে"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"শর্টকাট এডিট করুন"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"হয়ে গেছে"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 9306cfd..91c7701 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1747,7 +1747,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikacija skriva zahtjev za odobrenje, pa se vaš odgovor ne može potvrditi."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Dodirnite funkciju da je počnete koristiti:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Odaberite funkcije koje ćete koristiti s dugmetom Pristupačnost"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Odaberite funkcije koje ćete koristiti pomoću prečice tipke za jačinu zvuka"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Usluga <xliff:g id="SERVICE_NAME">%s</xliff:g> je isključena"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Uredi prečice"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gotovo"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 80420dd..cbe9c39 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1747,7 +1747,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Una aplicació està ocultant la sol·licitud de permís, de manera que la teva resposta no es pot verificar"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Toca una funció per començar a utilitzar-la:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Tria les funcions que vols utilitzar amb el botó d\'accessibilitat"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Tria les funcions que vols utilitzar amb la drecera per a tecles de volum"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> s\'ha desactivat"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edita les dreceres"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Fet"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index bc5cdfe..b9ceede 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1748,7 +1748,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Žádost o oprávnění skrývá nějaká aplikace, proto vaši odpověď nelze ověřit."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Chcete-li některou funkci začít používat, klepněte na ni:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Vyberte funkce, které budete používat s tlačítkem přístupnosti"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Vyberte funkce, které budete používat se zkratkou tlačítka hlasitosti"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Služba <xliff:g id="SERVICE_NAME">%s</xliff:g> byla vypnuta"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Upravit zkratky"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Hotovo"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 6cbe673..d66ebd9 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"En app skjuler anmodningen om tilladelse, så dit svar kan ikke verificeres."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tryk på en funktion for at bruge den:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Vælg, hvilke funktioner du vil bruge med knappen til hjælpefunktioner"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Vælg de funktioner, du vil bruge via lydstyrkeknapperne"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> er blevet deaktiveret"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Rediger genveje"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Udfør"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index dece83f..3879767 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Die Berechtigungsanfrage wird durch eine andere App verdeckt. Daher kann deine Antwort nicht geprüft werden."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Zum Auswählen der gewünschten Funktion tippen:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Funktionen auswählen, die du mit der Schaltfläche \"Bedienungshilfen\" verwenden möchtest"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Funktionen für Verknüpfung mit Lautstärketaste auswählen"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> wurde deaktiviert"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Kurzbefehle bearbeiten"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Fertig"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index cc179a4..28a5e55 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Μια εφαρμογή αποκρύπτει το αίτημα άδειας, με αποτέλεσμα να μην είναι δυνατή η επαλήθευση της απάντησής σας."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Πατήστε μια λειτουργία για να ξεκινήσετε να τη χρησιμοποιείτε:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Επιλέξτε τις λειτουργίες που θέλετε να χρησιμοποιείτε με το κουμπί προσβασιμότητας."</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Επιλέξτε τις λειτουργίες που θέλετε να χρησιμοποιείτε με τη συντόμευση κουμπιού έντασης ήχου"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Η υπηρεσία <xliff:g id="SERVICE_NAME">%s</xliff:g> έχει απενεργοποιηθεί."</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Επεξεργασία συντομεύσεων"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Τέλος"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index caa52c4..70d86e7 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"An app is obscuring the permission request so your response cannot be verified."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tap a feature to start using it:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Choose features to use with the Accessibility button"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Choose features to use with the volume key shortcut"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> has been turned off"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Done"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 3850b00..19547f8 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"An app is obscuring the permission request so your response cannot be verified."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tap a feature to start using it:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Choose features to use with the accessibility button"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Choose features to use with the volume key shortcut"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> has been turned off"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Done"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index bf5c61c..d3f0c64 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"An app is obscuring the permission request so your response cannot be verified."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tap a feature to start using it:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Choose features to use with the Accessibility button"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Choose features to use with the volume key shortcut"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> has been turned off"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Done"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index e829fa3..7c3be15 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"An app is obscuring the permission request so your response cannot be verified."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tap a feature to start using it:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Choose features to use with the Accessibility button"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Choose features to use with the volume key shortcut"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> has been turned off"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Done"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 0b9be3b..c1eade1 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"An app is obscuring the permission request so your response cannot be verified."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tap a feature to start using it:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Choose features to use with the accessibility button"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Choose features to use with the volume key shortcut"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> has been turned off"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit shortcuts"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Done"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 3814944..773edd3 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1747,7 +1747,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Una app está cubriendo la solicitud de permiso, por lo que no se puede verificar tu respuesta."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Presiona una función para comenzar a usarla:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Selecciona las funciones a utilizar con el botón de accesibilidad"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Selecciona las funciones a usar con las teclas de volumen"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Se desactivó <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar accesos directos"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Listo"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 215cf39..ff7d912 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1747,7 +1747,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Una aplicación está ocultando la solicitud de permiso, por lo que no se puede verificar tu respuesta."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Toca una función para empezar a usarla:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Selecciona qué funciones usar con el botón de accesibilidad"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Selecciona qué funciones usar con la tecla de volumen"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Se ha desactivado <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar accesos directos"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Hecho"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 4694efa..f313fb2 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Rakendus varjab loataotlust, nii et teie vastust ei saa kinnitada."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Puudutage funktsiooni, et selle kasutamist alustada."</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Valige funktsioonid, mida juurdepääsetavuse nupuga kasutada"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Valige helitugevuse nupu otsetee funktsioonid"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> on välja lülitatud"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Muuda otseteid"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Valmis"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 2cae18a..b0775d0 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -252,7 +252,7 @@
<string name="shutdown_confirm_question" msgid="796151167261608447">"Itzali egin nahi duzu?"</string>
<string name="reboot_safemode_title" msgid="5853949122655346734">"Berrabiarazi modu seguruan"</string>
<string name="reboot_safemode_confirm" msgid="1658357874737219624">"Modu seguruan berrabiarazi nahi duzu? Instalatutako hirugarrenen aplikazioak desgaituko dira. Berriro berrabiarazi ondoren leheneratuko dira."</string>
- <string name="recent_tasks_title" msgid="8183172372995396653">"Azkenak"</string>
+ <string name="recent_tasks_title" msgid="8183172372995396653">"Azkenaldikoak"</string>
<string name="no_recent_tasks" msgid="9063946524312275906">"Ez dago azkenaldian erabilitako aplikaziorik."</string>
<string name="global_actions" product="tablet" msgid="4412132498517933867">"Tabletaren aukerak"</string>
<string name="global_actions" product="tv" msgid="3871763739487450369">"Android TV gailuaren aukerak"</string>
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikazio bat baimen-eskaera oztopatzen ari da eta, ondorioz, ezin da egiaztatu erantzuna."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Eginbide bat erabiltzen hasteko, saka ezazu:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Aukeratu zein eginbide erabili nahi duzun Erabilerraztasuna botoiarekin"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Aukeratu zein eginbide erabili nahi duzun bolumen-botoien lasterbidearekin"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Desaktibatu da <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editatu lasterbideak"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Eginda"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 9a75d3a..5e474cd 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1183,7 +1183,7 @@
<string name="copyUrl" msgid="6229645005987260230">"کپی URL"</string>
<string name="selectTextMode" msgid="3225108910999318778">"انتخاب متن"</string>
<string name="undo" msgid="3175318090002654673">"لغو"</string>
- <string name="redo" msgid="7231448494008532233">"بازانجام"</string>
+ <string name="redo" msgid="7231448494008532233">"ازنو انجام دادن"</string>
<string name="autofill" msgid="511224882647795296">"تکمیل خودکار"</string>
<string name="textSelectionCABTitle" msgid="5151441579532476940">"انتخاب متن"</string>
<string name="addToDictionary" msgid="8041821113480950096">"افزودن به واژهنامه"</string>
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"پاسخ شما تأیید نشد زیرا یک برنامه درخواست اجازه را مسدود کرده است."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"برای استفاده از ویژگی، روی آن تکضرب بزنید:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"انتخاب ویژگیهای موردنظر برای استفاده با دکمه دسترسپذیری"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"انتخاب ویژگیهای موردنظر برای استفاده با میانبر کلید میزان صدا"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> خاموش شده است"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ویرایش میانبرها"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"تمام"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 1b2ddb0..dec5b64 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Sovellus peittää lupapyynnön, joten vastaustasi ei voi vahvistaa."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Aloita ominaisuuden käyttö napauttamalla sitä:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Valitse ominaisuudet, joita käytetään esteettömyyspainikkeella"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Valitse ominaisuudet, joita käytetään äänenvoimakkuuspikanäppäimellä"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> on laitettu pois päältä"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Muokkaa pikakuvakkeita"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Valmis"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index d3ebe5a..7cb9e06 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1747,7 +1747,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Une appli masque la demande d\'autorisation de sorte que votre réponse ne peut pas être vérifiée."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Toucher une fonctionnalité pour commencer à l\'utiliser :"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Choisir les fonctionnalités à utiliser à l\'aide du bouton d\'accessibilité"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Choisir les fonctionnalités à utiliser avec le raccourci des touches de volume"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> a été désactivé"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Modifier les raccourcis"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"OK"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index d617143..ca3998c 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1747,7 +1747,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Une application masque la demande d\'autorisation. Votre réponse ne peut donc pas être vérifiée."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Appuyez sur une fonctionnalité pour commencer à l\'utiliser :"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Choisir les fonctionnalités à utiliser avec le bouton Accessibilité"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Choisir les fonctionnalités à utiliser avec le raccourci des touches de volume"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Le service <xliff:g id="SERVICE_NAME">%s</xliff:g> a été désactivé"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Modifier les raccourcis"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"OK"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 9366f4e..e07218c 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Hai unha aplicación que está ocultando a solicitude de permiso, polo que non se pode verificar a túa resposta."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tocar unha función para comezar a utilizala:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Escoller as funcións que queres utilizar co botón Accesibilidade"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Escolle as funcións que queres utilizar co atallo da tecla de volume"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g>: desactivouse"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atallos"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Feito"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 6312704..2810b5e 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -266,7 +266,7 @@
<string name="global_action_logout" msgid="6093581310002476511">"સત્ર સમાપ્ત કરો"</string>
<string name="global_action_screenshot" msgid="2610053466156478564">"સ્ક્રીનશૉટ"</string>
<string name="bugreport_title" msgid="8549990811777373050">"બગ રિપોર્ટ"</string>
- <string name="bugreport_message" msgid="5212529146119624326">"આ, એક ઇ-મેઇલ સંદેશ તરીકે મોકલવા માટે, તમારા વર્તમાન ઉપકરણ સ્થિતિ વિશેની માહિતી એકત્રિત કરશે. એક બગ રિપોર્ટ પ્રારંભ કરીને તે મોકલવા માટે તૈયાર ન થઈ જાય ત્યાં સુધી તેમાં થોડો સમય લાગશે; કૃપા કરીને ધીરજ રાખો."</string>
+ <string name="bugreport_message" msgid="5212529146119624326">"આ, એક ઇ-મેઇલ મેસેજ તરીકે મોકલવા માટે, તમારા વર્તમાન ડિવાઇસના સ્ટેટસ વિશે માહિતી એકત્રિત કરશે. એક બગ રિપોર્ટના શરુ થવાથી લઈને મોકલવા માટે તૈયાર થવા સુધીની પ્રક્રિયામાં થોડો સમય લાગશે; કૃપા કરીને ધીરજ રાખો."</string>
<string name="bugreport_option_interactive_title" msgid="7968287837902871289">"ક્રિયાપ્રતિક્રિયાત્મક રિપોર્ટ"</string>
<string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"મોટાભાગના સંજોગોમાં આનો ઉપયોગ કરો. તે રિપોર્ટની પ્રગતિને ટ્રૅક કરવા, સમસ્યા વિશે વધુ વિગતો દાખલ કરવાની અને સ્ક્રીનશૉટ્સ લેવાની મંજૂરી આપે છે. તે કેટલાક ઓછા ઉપયોગમાં આવતાં વિભાગો કે જે જાણ કરવામાં વધુ સમય લેતાં હોય તેને છોડી દઈ શકે છે."</string>
<string name="bugreport_option_full_title" msgid="7681035745950045690">"પૂર્ણ રિપોર્ટ"</string>
@@ -291,7 +291,7 @@
<string name="notification_channel_security" msgid="8516754650348238057">"સુરક્ષા"</string>
<string name="notification_channel_car_mode" msgid="2123919247040988436">"કાર મોડ"</string>
<string name="notification_channel_account" msgid="6436294521740148173">"એકાઉન્ટ સ્થિતિ"</string>
- <string name="notification_channel_developer" msgid="1691059964407549150">"વિકાસકર્તા માટેના સંદેશા"</string>
+ <string name="notification_channel_developer" msgid="1691059964407549150">"ડેવલપર માટેના મેસેજ"</string>
<string name="notification_channel_developer_important" msgid="7197281908918789589">"ડેવલપર માટેના મહત્ત્વપૂર્ણ મેસેજ"</string>
<string name="notification_channel_updates" msgid="7907863984825495278">"અપડેટ્સ"</string>
<string name="notification_channel_network_status" msgid="2127687368725272809">"નેટવર્ક સ્થિતિ"</string>
@@ -324,7 +324,7 @@
<string name="permgrouplab_calendar" msgid="6426860926123033230">"કૅલેન્ડર"</string>
<string name="permgroupdesc_calendar" msgid="6762751063361489379">"તમારા કેલેન્ડરને ઍક્સેસ કરવાની"</string>
<string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
- <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS મેસેજ મોકલવાની અને જોવાની"</string>
+ <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS મેસેજ મોકલો અને જુઓ"</string>
<string name="permgrouplab_storage" msgid="17339216290379241">"ફાઇલો"</string>
<string name="permgroupdesc_storage" msgid="5378659041354582769">"તમારા ડિવાઇસ પરની ફાઇલો ઍક્સેસ કરો"</string>
<string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"મ્યુઝિક અને ઑડિયો"</string>
@@ -400,7 +400,7 @@
<string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"આ ઍપ, તમારા Android TV ડિવાઇસ પર સંગ્રહિત તમામ SMS (ટેક્સ્ટ) મેસેજ વાંચી શકે છે."</string>
<string name="permdesc_readSms" product="default" msgid="774753371111699782">"આ ઍપ, તમારા ફોન પર સંગ્રહિત તમામ SMS (ટેક્સ્ટ) મેસેજ વાંચી શકે છે."</string>
<string name="permlab_receiveWapPush" msgid="4223747702856929056">"ટેક્સ્ટ મેસેજ (WAP) મેળવો"</string>
- <string name="permdesc_receiveWapPush" msgid="1638677888301778457">"એપ્લિકેશનને WAP સંદેશા પ્રાપ્ત કરવાની અને તેના પર પ્રક્રિયા કરવાની મંજૂરી આપે છે. આ પરવાનગીમાં તમને દર્શાવ્યા વિના તમને મોકલેલ સંદેશાઓનું નિરીક્ષણ કરવાની અને કાઢી નાખવાની ક્ષમતાનો સમાવેશ થાય છે."</string>
+ <string name="permdesc_receiveWapPush" msgid="1638677888301778457">"ઍપને WAP મેસેજ મેળવવાની અને તેના પર પ્રક્રિયા કરવાની મંજૂરી આપે છે. આ પરવાનગીમાં તમને દર્શાવ્યા વિના તમને મોકલેલા મેસેજનું નિરીક્ષણ કરવાની અને ડિલીટ કરવાની ક્ષમતાનો સમાવેશ થાય છે."</string>
<string name="permlab_getTasks" msgid="7460048811831750262">"ચાલુ ઍપ્લિકેશનો પુનઃપ્રાપ્ત કરો"</string>
<string name="permdesc_getTasks" msgid="7388138607018233726">"એપ્લિકેશનને વર્તમાનમાં અને તાજેતરમાં ચાલી રહેલ Tasks વિશેની વિગતવાર માહિતી પુનઃપ્રાપ્ત કરવાની મંજૂરી આપે છે. આ એપ્લિકેશનને ઉપકરણ પર કઈ એપ્લિકેશન્સનો ઉપયોગ થાય છે તેના વિશેની માહિતી શોધવાની મંજૂરી આપી શકે છે."</string>
<string name="permlab_manageProfileAndDeviceOwners" msgid="639849495253987493">"પ્રોફાઇલ અને ડિવાઇસ માલિકોને મેનેજ કરો"</string>
@@ -1363,7 +1363,7 @@
<string name="sms_control_message" msgid="6574313876316388239">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> મોટા પ્રમાણમાં SMS મેસેજ મોકલી રહ્યું છે. શું તમે મેસેજ મોકલવાનું ચાલુ રાખવા માટે આ એપને મંજૂરી આપવા માગો છો?"</string>
<string name="sms_control_yes" msgid="4858845109269524622">"મંજૂરી આપો"</string>
<string name="sms_control_no" msgid="4845717880040355570">"નકારો"</string>
- <string name="sms_short_code_confirm_message" msgid="1385416688897538724">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> તમને <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b> પર સંદેશ મોકલવા માગે છે."</string>
+ <string name="sms_short_code_confirm_message" msgid="1385416688897538724">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>, <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b> પર મેસેજ મોકલવા માગે છે."</string>
<string name="sms_short_code_details" msgid="2723725738333388351">"આનાથી તમારા મોબાઇલ એકાઉન્ટ પર "<b>"શુલ્ક લાગી શકે છે"</b>"."</string>
<string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"આનાથી તમારા મોબાઇલ એકાઉન્ટ પર શુલ્ક લાગશે."</b></string>
<string name="sms_short_code_confirm_allow" msgid="920477594325526691">"મોકલો"</string>
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"કોઈ ઍપ પરવાનગીની વિનંતીને ઢાંકી રહી છે, તેથી તમારા પ્રતિસાદની ચકાસણી કરી શકાતી નથી."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"સુવિધાનો ઉપયોગ શરૂ કરવા તેના પર ટૅપ કરો:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ઍક્સેસિબિલિટી બટન વડે તમે ઉપયોગમાં લેવા માગો છો તે સુવિધાઓ પસંદ કરો"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"વૉલ્યૂમ કી શૉર્ટકટ વડે તમે ઉપયોગમાં લેવા માગો છો તે સુવિધાઓ પસંદ કરો"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> બંધ કરવામાં આવ્યું છે"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"શૉર્ટકટમાં ફેરફાર કરો"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"થઈ ગયું"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 02369f9..700e91a 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ऐप्लिकेशन की वजह से, अनुमति का अनुरोध समझने में परेशानी हो रही है. इसलिए, आपके जवाब की पुष्टि नहीं की जा सकी."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"किसी सुविधा का इस्तेमाल करने के लिए, उस पर टैप करें:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"सुलभता बटन पर टैप करके, इस्तेमाल करने के लिए सुविधाएं चुनें"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"चुनें कि आवाज़ कम या ज़्यादा करने वाले बटन के शॉर्टकट से आप किन सुविधाओं का इस्तेमाल करना चाहते हैं"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> को बंद कर दिया गया है"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"शॉर्टकट में बदलाव करें"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"हो गया"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 487d9e7..2596de2 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1747,7 +1747,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikacija prekriva upit za dopuštenje pa se vaš odgovor ne može potvrditi."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Dodirnite značajku da biste je počeli koristiti:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Odabir značajki za upotrebu pomoću gumba za Pristupačnost"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Odabir značajki za upotrebu pomoću prečaca tipki za glasnoću"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Usluga <xliff:g id="SERVICE_NAME">%s</xliff:g> je isključena"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Uredite prečace"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gotovo"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index ca8787d..09af506 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Az egyik alkalmazás eltakarja az engedélykérelmet, így az Ön válasza nem ellenőrizhető."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Koppintson valamelyik funkcióra a használatához:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Kiválaszthatja a Kisegítő lehetőségek gombbal használni kívánt funkciókat"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Kiválaszthatja a hangerőgombbal használni kívánt funkciókat"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> kikapcsolva"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Gyorsparancsszerkesztés"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Kész"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 273e7745..a28f413 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Հավելվածը թաքցնում է թույլտվության հայտը, ուստի ձեր պատասխանը հնարավոր չէ ստուգել։"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Ընտրեք՝ որ գործառույթն օգտագործել"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Ընտրեք գործառույթները, որոնք կբացվեն «Հատուկ գործառույթներ» կոճակի միջոցով"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Ընտրեք գործառույթները, որոնք կբացվեն ձայնի կարգավորման կոճակի միջոցով"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ծառայությունն անջատված է"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Փոփոխել դյուրանցումները"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Պատրաստ է"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 47588ff..76c89ea 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikasi menghalangi permintaan izin sehingga respons Anda tidak dapat diverifikasi."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Ketuk fitur untuk mulai menggunakannya:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Pilih fitur yang akan digunakan dengan tombol aksesibilitas"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Pilih fitur yang akan digunakan dengan pintasan tombol volume"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> telah dinonaktifkan"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit pintasan"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Selesai"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index a833c8d..3eb2e4b 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Forrit er að fela heimildarbeiðnina svo ekki er hægt að staðfesta svarið þitt."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Ýttu á eiginleika til að byrja að nota hann:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Veldu eiginleika sem á að nota með aðgengishnappinum"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Veldu eiginleika sem á að nota með flýtileið hljóðstyrkstakka"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Slökkt hefur verið á <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Breyta flýtileiðum"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Lokið"</string>
diff --git a/core/res/res/values-it-feminine/strings.xml b/core/res/res/values-it-feminine/strings.xml
index 141b467..1a69a63 100644
--- a/core/res/res/values-it-feminine/strings.xml
+++ b/core/res/res/values-it-feminine/strings.xml
@@ -20,6 +20,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="relationTypeFriend" msgid="3192092625893980574">"Amica"</string>
<string name="relationTypeSpouse" msgid="6916682664436031703">"Moglie"</string>
</resources>
diff --git a/core/res/res/values-it-masculine/strings.xml b/core/res/res/values-it-masculine/strings.xml
index 7310eb8..86c4408 100644
--- a/core/res/res/values-it-masculine/strings.xml
+++ b/core/res/res/values-it-masculine/strings.xml
@@ -20,6 +20,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="relationTypeFriend" msgid="3192092625893980574">"Amico"</string>
<string name="relationTypeSpouse" msgid="6916682664436031703">"Marito"</string>
</resources>
diff --git a/core/res/res/values-it-neuter/strings.xml b/core/res/res/values-it-neuter/strings.xml
index ce433d7..7c33e91 100644
--- a/core/res/res/values-it-neuter/strings.xml
+++ b/core/res/res/values-it-neuter/strings.xml
@@ -20,6 +20,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="relationTypeFriend" msgid="3192092625893980574">"Amicə"</string>
<string name="relationTypeSpouse" msgid="6916682664436031703">"Coniuge"</string>
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 662a9c0..29533d5 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -969,7 +969,7 @@
<string name="relationTypeChild" msgid="9076258911292693601">"Figlio"</string>
<string name="relationTypeDomesticPartner" msgid="7825306887697559238">"Convivente"</string>
<string name="relationTypeFather" msgid="3856225062864790596">"Padre"</string>
- <string name="relationTypeFriend" msgid="3192092625893980574">"Persona amica"</string>
+ <string name="relationTypeFriend" msgid="3192092625893980574">"Amico"</string>
<string name="relationTypeManager" msgid="2272860813153171857">"Dirigente"</string>
<string name="relationTypeMother" msgid="2331762740982699460">"Madre"</string>
<string name="relationTypeParent" msgid="4177920938333039882">"Genitore"</string>
@@ -1747,7 +1747,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Un\'app nasconde la tua richiesta di autorizzazione, per cui non abbiamo potuto verificare la tua risposta."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tocca una funzionalità per iniziare a usarla:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Scegli le funzionalità da usare con il pulsante Accessibilità"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Scegli le funzionalità da usare con la scorciatoia dei tasti del volume"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Il servizio <xliff:g id="SERVICE_NAME">%s</xliff:g> è stato disattivato"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Modifica scorciatoie"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Fine"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 37bffa4..52b6173 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1747,7 +1747,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"אפליקציה מסתירה את בקשת ההרשאה כך שלא ניתן לאמת את התשובה שלך."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"יש להקיש על תכונה כדי להתחיל להשתמש בה:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"בחירת תכונה לשימוש עם לחצן הנגישות"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"בחירת תכונות לשימוש עם מקש הקיצור לעוצמת הקול"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"שירות <xliff:g id="SERVICE_NAME">%s</xliff:g> כבוי"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"עריכת קיצורי הדרך"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"סיום"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index cce4abe..bcff813 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"権限のリクエストを遮っているアプリがあるため、同意の回答を確認できません。"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"使用を開始する機能をタップ:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ユーザー補助機能ボタンで使用する機能の選択"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"音量ボタンのショートカットで使用する機能の選択"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> はオフになっています"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ショートカットの編集"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"完了"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 0d8b047..0adebb0 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"აპი მალავს ნებართვის მოთხოვნას, ასე რომ, თქვენი პასუხი ვერ დადასტურდება."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"შეეხეთ ფუნქციას მისი გამოყენების დასაწყებად:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"აირჩიეთ ფუნქციები, რომელთა გამოყენებაც გსურთ მარტივი წვდომის ღილაკით"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"აირჩიეთ ფუნქციები, რომელთა გამოყენებაც გსურთ ხმის ღილაკის მალსახმობით"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> გამორთულია"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"მალსახმობების რედაქტირება"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"მზადაა"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 72a2a3b..d9ee240 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Қолданба рұқсат сұрауын жасырып тұрғандықтан, жауабыңыз расталмайды."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Функцияны пайдалана бастау үшін түртіңіз:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"\"Арнайы мүмкіндіктер\" түймесімен қолданылатын функцияларды таңдаңыз"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Дыбыс деңгейі пернелері тіркесімімен қолданылатын функцияларды таңдаңыз"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> қызметі өшірулі."</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Жылдам пәрмендерді өзгерту"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Дайын"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 2e5589e..f3dd775 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"កម្មវិធីមួយកំពុងបិទបាំងសំណើសុំការអនុញ្ញាត ដូច្នេះមិនអាចផ្ទៀងផ្ទាត់ការឆ្លើយតបរបស់អ្នកបានទេ។"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ចុចមុខងារណាមួយ ដើម្បចាប់ផ្ដើមប្រើ៖"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ជ្រើសរើសមុខងារ ដើម្បីប្រើជាមួយប៊ូតុងភាពងាយស្រួល"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ជ្រើសរើសមុខងារ ដើម្បីប្រើជាមួយផ្លូវកាត់គ្រាប់ចុចកម្រិតសំឡេង"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"បានបិទ <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"កែផ្លូវកាត់"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"រួចរាល់"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index e5a5092..a772e32 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1403,7 +1403,7 @@
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB ಪರಿಕರವನ್ನು ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string>
<string name="usb_notification_message" msgid="4715163067192110676">"ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗೆ ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"ಸಂಪರ್ಕಗೊಂಡಿರುವ ಸಾಧನವನ್ನು ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ. ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
- <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"ಅನ್ಲಾಗ್ ಆಡಿಯೋ ಪರಿಕರ ಪತ್ತೆಯಾಗಿದೆ"</string>
+ <string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"ಅನ್ಲಾಗ್ ಆಡಿಯೋ ಆ್ಯಕ್ಸೆಸರಿ ಪತ್ತೆಯಾಗಿದೆ"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"ಲಗತ್ತಿಸಲಾದ ಸಾಧನವು ಈ ಫೋನಿನೊಂದಿಗೆ ಹೊಂದಿಕೆಯಾಗುವುದಿಲ್ಲ. ಇನ್ನಷ್ಟು ತಿಳಿಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="adb_active_notification_title" msgid="408390247354560331">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆ ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
<string name="adb_active_notification_message" msgid="5617264033476778211">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆ ಆಫ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ಆ್ಯಪ್ವೊಂದು ಅನುಮತಿ ವಿನಂತಿಯನ್ನು ಮರೆಮಾಚುತ್ತಿರುವ ಕಾರಣ ನಿಮ್ಮ ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ಪರಿಶೀಲಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ವೈಶಿಷ್ಟ್ದ ಬಳಸುವುದನ್ನು ಪ್ರಾರಂಭಿಸಲು ಅದನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ ಬಟನ್ ಜೊತೆಗೆ ಬಳಸಲು ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ವಾಲ್ಯೂಮ್ ಕೀ ಶಾರ್ಟ್ಕಟ್ ಜೊತೆಗೆ ಬಳಸಲು ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ಅನ್ನು ಆಫ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ಎಡಿಟ್ ಮಾಡಿ"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ಪೂರ್ಣಗೊಂಡಿದೆ"</string>
@@ -2152,7 +2153,7 @@
<string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"ಸರಿ"</string>
<string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"ಆಫ್ ಮಾಡಿ"</string>
<string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
- <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"ವರ್ಧಿತ ನೋಟಿಫಿಕೇಶನ್ಗಳು Android 12 ರಲ್ಲಿ Android ಅಡಾಪ್ಟಿವ್ ನೋಟಿಫಿಕೇಶನ್ಗಳನ್ನು ಬದಲಾಯಿಸಿವೆ. ಈ ವೈಶಿಷ್ಟ್ಯವು ಸೂಚಿಸಿದ ಕ್ರಿಯೆಗಳು ಮತ್ತು ಪ್ರತ್ಯುತ್ತರಗಳನ್ನು ತೋರಿಸುತ್ತದೆ ಮತ್ತು ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳನ್ನು ಆಯೋಜಿಸುತ್ತದೆ.\n\nವರ್ಧಿತ ನೋಟಿಫಿಕೇಶನ್ಗಳು ಸಂಪರ್ಕ ಹೆಸರುಗಳು ಮತ್ತು ಸಂದೇಶಗಳಂತಹ ವೈಯಕ್ತಿಕ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಂತೆ ಎಲ್ಲಾ ಅಧಿಸೂಚನೆ ವಿಷಯವನ್ನು ಪ್ರವೇಶಿಸಬಹುದು. ಈ ವೈಶಿಷ್ಟ್ಯವು ಫೋನ್ ಕರೆಗಳಿಗೆ ಉತ್ತರಿಸುವುದು ಮತ್ತು \'ಅಡಚಣೆ ಮಾಡಬೇಡಿ\' ಅನ್ನು ನಿಯಂತ್ರಿಸುವಂತಹ ನೋಟಿಫಿಕೇಶನ್ಗಳನ್ನು ವಜಾಗೊಳಿಸಬಹುದು ಅಥವಾ ಪ್ರತಿಕ್ರಿಯಿಸಬಹುದು."</string>
+ <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"ವರ್ಧಿತ ನೋಟಿಫಿಕೇಶನ್ಗಳು Android 12 ರಲ್ಲಿ Android ಅಡಾಪ್ಟಿವ್ ನೋಟಿಫಿಕೇಶನ್ಗಳನ್ನು ಬದಲಾಯಿಸಿವೆ. ಈ ವೈಶಿಷ್ಟ್ಯವು ಸೂಚಿಸಿದ ಕ್ರಿಯೆಗಳು ಮತ್ತು ಪ್ರತ್ಯುತ್ತರಗಳನ್ನು ತೋರಿಸುತ್ತದೆ ಮತ್ತು ನಿಮ್ಮ ನೋಟಿಫಿಕೇಶನ್ಗಳನ್ನು ಆಯೋಜಿಸುತ್ತದೆ.\n\nವರ್ಧಿತ ನೋಟಿಫಿಕೇಶನ್ಗಳು ಸಂಪರ್ಕ ಹೆಸರುಗಳು ಮತ್ತು ಸಂದೇಶಗಳಂತಹ ವೈಯಕ್ತಿಕ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಂತೆ ಎಲ್ಲಾ ನೋಟಿಫಿಕೇಶನ್ ವಿಷಯವನ್ನು ಪ್ರವೇಶಿಸಬಹುದು. ಈ ವೈಶಿಷ್ಟ್ಯವು ಫೋನ್ ಕರೆಗಳಿಗೆ ಉತ್ತರಿಸುವುದು ಮತ್ತು \'ಅಡಚಣೆ ಮಾಡಬೇಡಿ\' ಅನ್ನು ನಿಯಂತ್ರಿಸುವಂತಹ ನೋಟಿಫಿಕೇಶನ್ಗಳನ್ನು ವಜಾಗೊಳಿಸಬಹುದು ಅಥವಾ ಪ್ರತಿಕ್ರಿಯಿಸಬಹುದು."</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ದೈನಂದಿನ ಸ್ಥಿತಿಯ ಮಾಹಿತಿಯ ನೋಟಿಫಿಕೇಶನ್"</string>
<string name="dynamic_mode_notification_title" msgid="1388718452788985481">"ಬ್ಯಾಟರಿ ಸೇವರ್ ಅನ್ನು ಆನ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="dynamic_mode_notification_summary" msgid="1639031262484979689">"ಬ್ಯಾಟರಿ ಬಾಳಿಕೆಯನ್ನು ವಿಸ್ತರಿಸಲು ಬ್ಯಾಟರಿ ಬಳಕೆಯನ್ನು ಕಡಿಮೆ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 1413170..0e47e59 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"앱에서 권한 요청을 가려서 응답을 확인할 수 없습니다."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"기능을 사용하려면 탭하세요"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"접근성 버튼으로 사용할 기능 선택"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"볼륨 키 단축키로 사용할 기능 선택"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g>이(가) 사용 중지됨"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"단축키 수정"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"완료"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 112bf0a..4c2ee5f 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Колдонмо уруксат суроону жашырып койгондуктан, жообуңузду ырастоо мүмкүн эмес."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Функцияны колдонуп баштоо үчүн аны таптап коюңуз:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Атайын мүмкүнчүлүктөр баскычы менен колдонгуңуз келген функцияларды тандаңыз"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Үндү катуулатуу/акырындатуу баскычтары менен кайсы функцияларды иштеткиңиз келет?"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> өчүрүлдү"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Кыска жолдорду түзөтүү"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Бүттү"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index ba43481..b627503 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ແອັບໜຶ່ງກຳລັງປິດບັງຄຳຮ້ອງຂໍການອະນຸຍາດ ດັ່ງນັ້ນຈຶ່ງບໍ່ສາມາດຢັ້ງຢືນຄຳຕອບຂອງທ່ານໄດ້."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ແຕະໃສ່ຄຸນສົມບັດໃດໜຶ່ງເພື່ອເລີ່ມການນຳໃຊ້ມັນ:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ເລືອກຄຸນສົມບັດເພື່ອໃຊ້ກັບປຸ່ມການຊ່ວຍເຂົ້າເຖິງ"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ເລືອກຄຸນສົມບັດເພື່ອໃຊ້ກັບທາງລັດປຸ່ມລະດັບສຽງ"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"ປິດ <xliff:g id="SERVICE_NAME">%s</xliff:g> ໄວ້ແລ້ວ"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ແກ້ໄຂທາງລັດ"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ແລ້ວໆ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index ad30d80..8eace89 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1748,7 +1748,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Programa užstoja leidimo užklausą, todėl negalima patvirtinti jūsų atsakymo."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Norėdami naudoti funkciją, palieskite ją:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Funkcijų, kurioms bus naudojamas pritaikomumo mygtukas, pasirinkimas"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Funkcijų, kurioms bus naudojamas garsumo spartusis klavišas, pasirinkimas"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Paslauga „<xliff:g id="SERVICE_NAME">%s</xliff:g>“ išjungta"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Redaguoti sparčiuosius klavišus"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Atlikta"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 329bbc3..01fb9da 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1747,7 +1747,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Kāda lietotne padara atļaujas pieprasījumu nesaprotamu, tāpēc nevar verificēt jūsu atbildi."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Pieskarieties funkcijai, lai sāktu to izmantot"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Izvēlieties funkcijas, ko izmantot ar pieejamības pogu"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Izvēlieties funkcijas, ko izmantot ar skaļuma pogu saīsni"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Pakalpojums <xliff:g id="SERVICE_NAME">%s</xliff:g> ir izslēgts."</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Rediģēt īsinājumtaustiņus"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gatavs"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 4bb0340..dbc4b75 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Апликација го прикрива барањето за дозвола, па вашиот одговор не може да се потврди."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Допрете на функција за да почнете да ја користите:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Изберете ги функциите што ќе ги користите со копчето за пристапност"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Изберете ги функциите што ќе ги користите со кратенката за копчето за јачина на звук"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> е исклучена"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Изменете ги кратенките"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Готово"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 72e522d..2b1c52f 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ഒരു ആപ്പ്, അനുമതി അഭ്യർത്ഥന മറയ്ക്കുന്നതിനാൽ നിങ്ങളുടെ പ്രതികരണം പരിശോധിച്ചുറപ്പിക്കാനാകില്ല."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ഉപയോഗിച്ച് തുടങ്ങാൻ ഫീച്ചർ ടാപ്പ് ചെയ്യുക:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ഉപയോഗസഹായി ബട്ടണിന്റെ സഹായത്തോടെ, ഉപയോഗിക്കാൻ ഫീച്ചറുകൾ തിരഞ്ഞെടുക്കുക"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"വോളിയം കീ കുറുക്കുവഴിയിലൂടെ ഉപയോഗിക്കാൻ ഫീച്ചറുകൾ തിരഞ്ഞെടുക്കുക"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ഓഫാക്കിയിരിക്കുന്നു"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"കുറുക്കുവഴികൾ തിരുത്തുക"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"പൂർത്തിയാക്കി"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 4398975..bf2f78c 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Апп зөвшөөрлийн хүсэлтийг хааж байгаа тул таны хариултыг баталгаажуулах боломжгүй."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Үүнийг ашиглаж эхлэхийн тулд онцлог дээр товшино уу:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Хандалтын товчлуурын тусламжтай ашиглах онцлогуудыг сонгоно уу"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Дууны түвшний түлхүүрийн товчлолын тусламжтай ашиглах онцлогуудыг сонгоно уу"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g>-г унтраалаа"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Товчлолуудыг засах"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Болсон"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index ac39d55..67c3b98 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"परवानगी मागणारी विनंती अॅपमुळे अस्पष्ट होत असल्याने, तुमच्या प्रतिसादाची पडताळणी केली जाऊ शकत नाही."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"वैशिष्ट्य वापरणे सुरू करण्यासाठी त्यावर टॅप करा:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"अॅक्सेसिबिलिटी बटणासोबत वापरायची असलेली ॲप्स निवडा"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"व्हॉल्यूम की शॉर्टकटसोबत वापरायची असलेली ॲप्स निवडा"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> बंद केले आहे"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"शॉर्टकट संपादित करा"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"पूर्ण झाले"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 88eef46..5eac793 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Apl menghalang permintaan kebenaran, maka jawapan anda tidak dapat disahkan."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Ketik ciri untuk mula menggunakan ciri itu:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Pilih ciri untuk digunakan dengan butang kebolehaksesan"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Pilih ciri untuk digunakan dengan pintasan kekunci kelantangan"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> telah dimatikan"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edit pintasan"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Selesai"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index d5c1fbd..b09539c 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"အက်ပ်တစ်ခုသည် ခွင့်ပြုချက်တောင်းဆိုမှုကို ပိတ်နေသဖြင့် သင့်တုံ့ပြန်မှုကို စိစစ်၍မရပါ။"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ဝန်ဆောင်မှုကို စတင်အသုံးပြုရန် တို့ပါ−"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"အများသုံးနိုင်မှု ခလုတ်ဖြင့် အသုံးပြုရန် ဝန်ဆောင်မှုများကို ရွေးပါ"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"အသံခလုတ် ဖြတ်လမ်းလင့်ခ်ဖြင့် အသုံးပြုရန် ဝန်ဆောင်မှုများကို ရွေးပါ"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ကို ပိတ်ထားသည်"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ဖြတ်လမ်းများကို တည်းဖြတ်ရန်"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ပြီးပြီ"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 53b6ad5..8feb6e9 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"En app dekker forespørselen om tillatelse, så svaret ditt kan ikke bekreftes."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Trykk på en funksjon for å begynne å bruke den:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Velg funksjonene du vil bruke med Tilgjengelighet-knappen"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Velg funksjonene du vil bruke med volumtastsnarveien"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> er slått av"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Endre snarveier"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Ferdig"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 2a23e87..9f3530a 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1097,7 +1097,7 @@
<string name="js_dialog_before_unload_positive_button" msgid="4274257182303565509">"यस पृष्ठलाई छोड्नुहोस्"</string>
<string name="js_dialog_before_unload_negative_button" msgid="3873765747622415310">"यही पृष्ठमा रहनुहोस्"</string>
<string name="js_dialog_before_unload" msgid="7213364985774778744">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nके तपाईं यो पेजबाट नेभिगेट गर्न चाहनु हुन्छ भन्ने निश्चत छ?"</string>
- <string name="autofill_window_title" msgid="4379134104008111961">"<xliff:g id="SERVICENAME">%1$s</xliff:g> मार्फत स्वतः भरण गर्नुहोस्"</string>
+ <string name="autofill_window_title" msgid="4379134104008111961">"<xliff:g id="SERVICENAME">%1$s</xliff:g> मार्फत अटोफिल गर्नुहोस्"</string>
<string name="permlab_setAlarm" msgid="1158001610254173567">"एउटा आलर्म सेट गर्नुहोस्"</string>
<string name="permdesc_setAlarm" msgid="2185033720060109640">"स्थापना गरिएको सङ्केत घडी एपमा सङ्केत समय मिलाउन एपलाई अनुमति दिन्छ। केही सङ्केत घडी एपहरूले यो सुविधा कार्यान्वयन नगर्न सक्छन्।"</string>
<string name="permlab_addVoicemail" msgid="4770245808840814471">"भ्वाइसमेल थप गर्नुहोस्"</string>
@@ -1184,7 +1184,7 @@
<string name="selectTextMode" msgid="3225108910999318778">"पाठ चयन गर्नुहोस्"</string>
<string name="undo" msgid="3175318090002654673">"अन्डू गर्नुहोस्"</string>
<string name="redo" msgid="7231448494008532233">"रिडू गर्नुहोस्"</string>
- <string name="autofill" msgid="511224882647795296">"स्वतः भरण"</string>
+ <string name="autofill" msgid="511224882647795296">"अटोफिल"</string>
<string name="textSelectionCABTitle" msgid="5151441579532476940">"पाठ चयनता"</string>
<string name="addToDictionary" msgid="8041821113480950096">"शब्दकोशमा थप्नुहोस्"</string>
<string name="deleteText" msgid="4200807474529938112">"मेट्नुहोस्"</string>
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"कुनै एपका कारण अनुमतिसम्बन्धी अनुरोध बुझ्न कठिनाइ भइरहेकाले तपाईंको जवाफको पुष्टि गर्न सकिएन।"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"कुनै सुविधा प्रयोग गर्न थाल्न उक्त सुविधामा ट्याप गर्नुहोस्:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"पहुँचको बटनमार्फत प्रयोग गर्न चाहेका सुविधाहरू छनौट गर्नुहोस्"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"भोल्युम कुञ्जीको सर्टकटमार्फत प्रयोग गर्न चाहेका सुविधाहरू छनौट गर्नुहोस्"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> निष्क्रिय पारिएको छ"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"सर्टकटहरू सम्पादन गर्नुहोस्"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"सम्पन्न भयो"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 5106f7c..8209504 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1721,7 +1721,7 @@
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Verwijderen"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Volume verhogen tot boven het aanbevolen niveau?\n\nAls je langere tijd op hoog volume naar muziek luistert, raakt je gehoor mogelijk beschadigd."</string>
- <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Wil je blijven luisteren op hoog volume?\n\nHet hoofdtelefoonvolume is langer dan de aanbevolen tijd hoog geweest. Dit kan je gehoor beschadigen."</string>
+ <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Wil je blijven luisteren op hoog volume?\n\nHet koptelefoonvolume is langer dan de aanbevolen tijd hoog geweest. Dit kan je gehoor beschadigen."</string>
<string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Hard geluid gedetecteerd\n\nHet hoofdtelefoonvolume is hoger dan aanbevolen. Dit kan je gehoor beschadigen."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Snelkoppeling toegankelijkheid gebruiken?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Als de snelkoppeling aanstaat, houd je beide volumeknoppen 3 seconden ingedrukt om een toegankelijkheidsfunctie te starten."</string>
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Een app dekt het verzoek om rechten af, waardoor je reactie niet kan worden geverifieerd."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tik op een functie om deze te gebruiken:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Functies kiezen voor gebruik met de knop Toegankelijkheid"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Functies kiezen voor gebruik met de sneltoets via de volumeknop"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> is uitgezet"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Snelkoppelingen bewerken"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Klaar"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index f9e9374..45b6e9a 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ଏକ ଆପ ଅନୁମତି ଅନୁରୋଧକୁ ଅସ୍ପଷ୍ଟ କରୁଛି ତେଣୁ ଆପଣଙ୍କ ଉତ୍ତରକୁ ଯାଞ୍ଚ କରାଯାଇପାରିବ ନାହିଁ।"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ଏକ ଫିଚର୍ ବ୍ୟବହାର କରିବା ଆରମ୍ଭ କରିବାକୁ ଏହାକୁ ଟାପ୍ କରନ୍ତୁ:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ଆକ୍ସେସିବିଲିଟୀ ବଟନ୍ ସହିତ ବ୍ୟବହାର କରିବାକୁ ଫିଚରଗୁଡ଼ିକ ବାଛନ୍ତୁ"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ଭଲ୍ୟୁମ୍ କୀ ସର୍ଟକଟ୍ ସହିତ ବ୍ୟବହାର କରିବାକୁ ଫିଚରଗୁଡ଼ିକ ବାଛନ୍ତୁ"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ବନ୍ଦ ହୋଇଯାଇଛି"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ସର୍ଟକଟଗୁଡ଼ିକୁ ଏଡିଟ କରନ୍ତୁ"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ହୋଇଗଲା"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index e309832..c6d0b9f 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ਕੋਈ ਐਪ ਇਜਾਜ਼ਤ ਸੰਬੰਧੀ ਬੇਨਤੀ ਨੂੰ ਅਸਪਸ਼ਟ ਕਰ ਰਹੀ ਹੈ, ਇਸ ਲਈ ਤੁਹਾਡੇ ਜਵਾਬ ਦੀ ਪੁਸ਼ਟੀ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ਕਿਸੇ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਵਰਤਣਾ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਉਸ \'ਤੇ ਟੈਪ ਕਰੋ:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ਪਹੁੰਚਯੋਗਤਾ ਬਟਨ ਨਾਲ ਵਰਤਣ ਲਈ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਚੁਣੋ"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ਅਵਾਜ਼ ਕੁੰਜੀ ਸ਼ਾਰਟਕੱਟ ਨਾਲ ਵਰਤਣ ਲਈ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਚੁਣੋ"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ਨੂੰ ਬੰਦ ਕਰ ਦਿੱਤਾ ਗਿਆ ਹੈ"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ਸ਼ਾਰਟਕੱਟਾਂ ਦਾ ਸੰਪਾਦਨ ਕਰੋ"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ਹੋ ਗਿਆ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index b6f70d6..0ae3bbf 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1748,7 +1748,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikacja zasłania prośbę o uprawnienia, więc nie można zweryfikować Twojej odpowiedzi."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Wybierz funkcję, aby zacząć z niej korzystać:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Wybierz funkcje, których chcesz używać z przyciskiem ułatwień dostępu"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Wybierz funkcje, do których chcesz używać skrótu z klawiszami głośności"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Usługa <xliff:g id="SERVICE_NAME">%s</xliff:g> została wyłączona"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Edytuj skróty"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"OK"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index d5035e0..e025d19 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1747,7 +1747,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Um app está ocultando a solicitação de permissão e impedindo a verificação da sua resposta."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Toque em um recurso para começar a usá-lo:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Escolha recursos para usar com o botão de acessibilidade"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Escolha recursos para usar com o atalho da tecla de volume"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"O <xliff:g id="SERVICE_NAME">%s</xliff:g> foi desativado"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atalhos"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Concluído"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index a9ba018..71940ef 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1747,7 +1747,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Uma app está a ocultar o pedido de autorização e, por isso, não é possível validar a sua resposta."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Toque numa funcionalidade para começar a utilizá-la:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Escolha funcionalidades para utilizar com o botão Acessibilidade"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Escolha funcionalidades para usar com o atalho das teclas de volume"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"O serviço <xliff:g id="SERVICE_NAME">%s</xliff:g> foi desativado."</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atalhos"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Concluído"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index d5035e0..e025d19 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1747,7 +1747,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Um app está ocultando a solicitação de permissão e impedindo a verificação da sua resposta."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Toque em um recurso para começar a usá-lo:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Escolha recursos para usar com o botão de acessibilidade"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Escolha recursos para usar com o atalho da tecla de volume"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"O <xliff:g id="SERVICE_NAME">%s</xliff:g> foi desativado"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editar atalhos"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Concluído"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 444dbd4..7e5e7c0 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1747,7 +1747,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"O aplicație blochează solicitarea de permisiune, așa că răspunsul nu se poate verifica."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Atinge o funcție ca să începi să o folosești:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Alege funcțiile pe care să le folosești cu butonul de accesibilitate"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Alege funcțiile pentru comanda rapidă a butonului de volum"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> a fost dezactivat"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Editează comenzile rapide"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gata"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 46e7b9d..22501f2 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1748,7 +1748,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Невозможно принять ваш ответ, поскольку запрос разрешения скрыт другим приложением."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Выберите, какую функцию использовать:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Выберите функции, которые будут запускаться с помощью кнопки специальных возможностей"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Выберите функции, которые будут запускаться с помощью кнопки регулировки громкости"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Сервис \"<xliff:g id="SERVICE_NAME">%s</xliff:g>\" отключен."</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Изменить ярлыки"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Готово"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index fb03569..af835d9 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"යෙදුමක් අවසර ඉල්ලීම අඳුරු කරන බැවින්, ඔබේ ප්රතිචාරය සත්යාපනය කළ නොහැක."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"එය භාවිත කිරීම ආරම්භ කිරීමට විශේෂාංගයක් තට්ටු කරන්න:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ප්රවේශ්යතා බොත්තම සමග භාවිත කිරීමට විශේෂාංග තෝරා ගන්න"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"හඬ පරිමා යතුරු කෙටිමග සමග භාවිත කිරීමට විශේෂාංග තෝරා ගන්න"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ක්රියාවිරහිත කර ඇත"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"කෙටිමං සංස්කරණ කරන්න"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"නිමයි"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index bde470e..3289bbc 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1748,7 +1748,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikácia zakrýva žiadosť o povolenie, takže vaša odpoveď sa nedá overiť."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Klepnutím na funkciu ju začnite používať:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Výber funkcií, ktoré chcete používať tlačidlom dostupnosti"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Výber funkcií, ktoré chcete používať klávesovou skratkou"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Služba <xliff:g id="SERVICE_NAME">%s</xliff:g> bola vypnutá"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Upraviť skratky"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Hotovo"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index b70322b..99ce046 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1748,7 +1748,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Aplikacija zakriva zahtevo za dovoljenje, zato ni mogoče potrditi vašega odgovora."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Če želite začeti uporabljati funkcijo, se je dotaknite:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Izberite funkcije, ki jih želite uporabljati z gumbom za dostopnost"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Izberite funkcije, ki jih želite uporabljati z bližnjico na tipki za glasnost"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Storitev <xliff:g id="SERVICE_NAME">%s</xliff:g> je izklopljena"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Uredi bližnjice"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Končano"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 3040597..d8fe109 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Një aplikacion po fsheh kërkesën për leje, prandaj përgjigja jote nuk mund të verifikohet."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Trokit te një veçori për të filluar ta përdorësh atë:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Zgjidh veçoritë që do të përdorësh me butonin e qasshmërisë"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Zgjidh veçoritë që do të përdorësh me shkurtoren e tastit të volumit"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> është çaktivizuar"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Redakto shkurtoret"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"U krye"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index f8e5a79..0451b56 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1747,7 +1747,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Апликација крије захтев за дозволу, па одговор не може да се верификује."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Додирните неку функцију да бисте почели да је користите:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Одаберите функције које ћете користити са дугметом Приступачност"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Одаберите функције за пречицу тастером јачине звука"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Услуга <xliff:g id="SERVICE_NAME">%s</xliff:g> је искључена"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Измените пречице"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Готово"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 8e08c6b..9bde6af 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"En app döljer behörighetsbegäran så det går inte att verifiera svaret."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Tryck på funktioner som du vill aktivera:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Välj vilka funktioner du vill använda med hjälp av tillgänglighetsknappen"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Välj att funktioner att använda med hjälp av volymknappskortkommandot"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> har inaktiverats"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Redigera genvägar"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Klar"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index a9385c1..c286eeb 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Programu inazuia ombi la ruhusa kwa hivyo jibu lako haliwezi kuthibitishwa."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Gusa kipengele ili uanze kukitumia:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Chagua vipengele vya kutumia na kitufe cha zana za ufikivu"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Chagua vipengele vya kutumia na njia ya mkato ya kitufe cha sauti"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Huduma ya <xliff:g id="SERVICE_NAME">%s</xliff:g> imezimwa"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Kubadilisha njia za mkato"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Nimemaliza"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 6ba7a54..b1ce514 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"அணுகல் கோரிக்கையை ஓர் ஆப்ஸ் மறைப்பதால் உங்கள் பதிலைச் சரிபார்க்க முடியாது."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ஒரு அம்சத்தைப் பயன்படுத்த அதைத் தட்டவும்:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"அணுகல்தன்மை பட்டன் மூலம் பயன்படுத்த விரும்பும் அம்சங்களைத் தேர்வுசெய்யுங்கள்"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"ஒலியளவு விசை ஷார்ட்கட் மூலம் பயன்படுத்த விரும்பும் அம்சங்களைத் தேர்வுசெய்யுங்கள்"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ஆஃப் செய்யப்பட்டுள்ளது"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"ஷார்ட்கட்களை மாற்று"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"முடிந்தது"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index ae1a2c3..4b655d1 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ఒక యాప్ అనుమతి రిక్వెస్ట్కు అడ్డు తగులుతోంది కాబట్టి మీ సమాధానం వెరిఫై చేయడం సాధ్యం కాదు."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ఫీచర్ని ఉపయోగించడం ప్రారంభించడానికి, దాన్ని ట్యాప్ చేయండి:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"యాక్సెసిబిలిటీ బటన్తో ఉపయోగించడానికి ఫీచర్లను ఎంచుకోండి"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"వాల్యూమ్ కీ షార్ట్కట్తో ఉపయోగించడానికి ఫీచర్లను ఎంచుకోండి"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ఆఫ్ చేయబడింది"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"షార్ట్కట్లను ఎడిట్ చేయండి"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"పూర్తయింది"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 655cf4c..d979c34 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"มีแอปหนึ่งบดบังคำขอสิทธิ์ เราจึงยืนยันการตอบกลับของคุณไม่ได้"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"แตะฟีเจอร์เพื่อเริ่มใช้"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"เลือกฟีเจอร์ที่จะใช้กับปุ่มการช่วยเหลือพิเศษ"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"เลือกฟีเจอร์ที่จะใช้กับทางลัดปุ่มปรับระดับเสียง"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"ปิด <xliff:g id="SERVICE_NAME">%s</xliff:g> แล้ว"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"แก้ไขทางลัด"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"เสร็จ"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 885be75..fbbb32c 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1721,7 +1721,7 @@
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Alisin"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Lakasan ang volume nang lagpas sa inirerekomendang antas?\n\nMaaaring mapinsala ng pakikinig sa malakas na volume sa loob ng mahahabang panahon ang iyong pandinig."</string>
- <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Magpatuloy sa pakikinig nang may malakas na volume?\n\nNaging malakas ang volume nang mas matagal na sa inirerekomenda, at posible nitong mapinsala ang pandinig mo"</string>
+ <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Magpatuloy sa pakikinig nang may malakas na volume?\n\nMalakas ang volume nang mas matagal na sa inirerekomenda, at posible nitong mapinsala ang pandinig mo"</string>
<string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Naka-detect ng malakas na tunog\n\nMas malakas ang volume kaysa sa inirerekomenda, at posible nitong mapinsala ang pandinig mo"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gagamitin ang Shortcut sa Accessibility?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kapag naka-on ang shortcut, magsisimula ang isang feature ng pagiging naa-access kapag pinindot ang parehong button ng volume."</string>
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"May app na pumipigil sa kahilingan sa pahintulot kaya hindi ma-verify ang iyong sagot."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"I-tap ang isang feature para simulan itong gamitin:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Pumili ng mga feature na gagana sa pamamagitan ng button ng accessibility"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Pumili ng mga feature na gagana sa pamamagitan ng shortcut ng volume key"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Na-off ang <xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"I-edit ang mga shortcut"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Tapos na"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index a5d064e..a015a8f 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Bir uygulama, izin isteğini gizlediğinden yanıtınız doğrulanamıyor."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Kullanmaya başlamak için bir özelliğe dokunun:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Erişilebilirlik düğmesiyle kullanılacak özellikleri seçin"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Ses tuşu kısayoluyla kullanılacak özellikleri seçin"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> kapatıldı"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Kısayolları düzenle"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Bitti"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 5514ba4..e41d3ce 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1748,7 +1748,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Інший додаток перекриває запит на доступ, тому вашу відповідь не вдається підтвердити."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Натисніть функцію, щоб почати використовувати її:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Виберіть функції для кнопки спеціальних можливостей"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Виберіть функції для комбінації з клавішами гучності"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"Сервіс <xliff:g id="SERVICE_NAME">%s</xliff:g> вимкнено"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Змінити"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Готово"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 7c6317c..d2f0898 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"ایپ اجازت کی درخواست کو مبہم کر رہی ہے لہذا آپ کے جواب کی تصدیق نہیں کی جا سکتی۔"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"ایک خصوصیت کا استعمال شروع کرنے کیلئے اسے تھپتھپائیں:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"ایکسیسبیلٹی بٹن کے ساتھ استعمال کرنے کیلئے خصوصیات منتخب کریں"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"والیوم کلید کے شارٹ کٹ کے ساتھ استعمال کرنے کیلئے خصوصیات منتخب کریں"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> کو آف کر دیا گیا ہے"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"شارٹ کٹس میں ترمیم کریں"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"ہو گیا"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 868a927..e9bc805 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Ilova ruxsat olish talabini berkitmoqda, shu sababdan javobingizni tasdiqlash imkonsiz."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Kerakli funksiyani tanlang"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Qulayliklar tugmasi bilan foydalanish uchun funksiyalarni tanlang"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Tovush tugmasi bilan ishga tushiriladigan funksiyalarni tanlang"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> faolsizlantirildi"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Tezkor tugmalarni tahrirlash"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"OK"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index c7337ef..510edab 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"Một ứng dụng đang che khuất yêu cầu quyền này nên chúng tôi không thể xác minh phản hồi của bạn."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Nhấn vào một tính năng để bắt đầu sử dụng:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Chọn các tính năng để dùng với nút hỗ trợ tiếp cận"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Chọn các tính năng để dùng với phím tắt là phím âm lượng"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> đã bị tắt"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Chỉnh sửa phím tắt"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Xong"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 378e548..bcb54dc 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"应用遮挡了权限请求,因此我们无法验证您的回复。"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"点按相应功能即可开始使用:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"选择可通过“无障碍”按钮使用的功能"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"选择可通过音量键快捷方式使用的功能"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"已关闭<xliff:g id="SERVICE_NAME">%s</xliff:g>"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"修改快捷方式"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"完成"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 5a9db4f..875eec0 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"有應用程式阻擋權限要求,因此系統無法驗證你的回應。"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"輕按即可開始使用所需功能:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"選擇要配搭無障礙功能按鈕使用的功能"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"選擇要用音量快速鍵的功能"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> 已關閉"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"編輯捷徑"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"完成"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 5cfca16..efa4c51 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"應用程式遮擋了權限要求,因此系統無法驗證你的回覆。"</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"輕觸即可開始使用所需功能:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"選擇要搭配無障礙工具按鈕使用的功能"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"選擇要搭配音量快速鍵使用的功能"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"「<xliff:g id="SERVICE_NAME">%s</xliff:g>」已關閉"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"編輯捷徑"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"完成"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index c8e49a1..67a4361 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1746,7 +1746,8 @@
<string name="accessibility_dialog_touch_filtered_warning" msgid="3741940116597822451">"I-app ifihla isicelo semvume ngakho impendulo yakho ayikwazi ukuqinisekiswa."</string>
<string name="accessibility_select_shortcut_menu_title" msgid="6002726538854613272">"Thepha isici ukuqala ukusisebenzisa:"</string>
<string name="accessibility_edit_shortcut_menu_button_title" msgid="239446795930436325">"Khetha izici ongazisebenzisa nenkinobho yokufinyeleleka"</string>
- <string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Khetha izici ongazisebenzisa nesinqamuleli sokhiye wevolumu"</string>
+ <!-- no translation found for accessibility_edit_shortcut_menu_volume_title (2245540598834891500) -->
+ <skip />
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"I-<xliff:g id="SERVICE_NAME">%s</xliff:g> ivaliwe"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Hlela izinqamuleli"</string>
<string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Kwenziwe"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b6468ee..38aff75 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4153,6 +4153,9 @@
<!-- Indicating if keyboard vibration settings supported or not. -->
<bool name="config_keyboardVibrationSettingsSupported">false</bool>
+ <!-- Indicating if ringtone vibration settings supported or not. -->
+ <bool name="config_ringtoneVibrationSettingsSupported">false</bool>
+
<!-- If the device should still vibrate even in low power mode, for certain priority vibrations
(e.g. accessibility, alarms). This is mainly for Wear devices that don't have speakers. -->
<bool name="config_allowPriorityVibrationsInLowPowerMode">false</bool>
@@ -7030,6 +7033,10 @@
{@link InputDevice#SOURCE_ROTARY_ENCODER}s. -->
<bool name="config_viewBasedRotaryEncoderHapticsEnabled">false</bool>
+ <!-- Whether the scroll haptic feedback implementation is enabled for
+ {@link InputDevice#SOURCE_TOUCHSCREEN}s. -->
+ <bool name="config_viewTouchScreenHapticScrollFeedbackEnabled">false</bool>
+
<!-- Whether the media player is shown on the quick settings -->
<bool name="config_quickSettingsShowMediaPlayer">true</bool>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f404666..606c7fd 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4804,9 +4804,9 @@
</string>
<!-- Title for accessibility edit shortcut selection menu dialog, and dialog is triggered
- from volume key shortcut. [CHAR LIMIT=100] -->
+ from volume keys shortcut. [CHAR LIMIT=100] -->
<string name="accessibility_edit_shortcut_menu_volume_title">Choose features to use with the
- volume key shortcut
+ volume keys shortcut
</string>
<!-- Text for showing the warning to user when uncheck the legacy app item in the accessibility
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 74922ac..4693894 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2132,6 +2132,7 @@
<java-symbol type="dimen" name="config_hapticChannelMaxVibrationAmplitude" />
<java-symbol type="dimen" name="config_keyboardHapticFeedbackFixedAmplitude" />
<java-symbol type="bool" name="config_keyboardVibrationSettingsSupported" />
+ <java-symbol type="bool" name="config_ringtoneVibrationSettingsSupported" />
<java-symbol type="integer" name="config_vibrationWaveformRampStepDuration" />
<java-symbol type="bool" name="config_ignoreVibrationsOnWirelessCharger" />
<java-symbol type="integer" name="config_vibrationWaveformRampDownDuration" />
@@ -5490,8 +5491,11 @@
<java-symbol type="bool" name="config_tvExternalInputLoggingDisplayNameFilterEnabled" />
<java-symbol type="array" name="config_tvExternalInputLoggingDeviceOnScreenDisplayNames" />
<java-symbol type="array" name="config_tvExternalInputLoggingDeviceBrandNames" />
+
+ <!-- Scroll Feedback Configs -->
<java-symbol type="bool" name="config_viewRotaryEncoderHapticScrollFedbackEnabled" />
<java-symbol type="bool" name="config_viewBasedRotaryEncoderHapticsEnabled" />
+ <java-symbol type="bool" name="config_viewTouchScreenHapticScrollFeedbackEnabled" />
<java-symbol type="bool" name="config_quickSettingsShowMediaPlayer" />
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 452ae04..d35bfb7 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -131,7 +131,7 @@
<item name="progressBarStyleSmallInverse">@style/Widget.DeviceDefault.ProgressBar.Small.Inverse</item>
<item name="progressBarStyleLargeInverse">@style/Widget.DeviceDefault.ProgressBar.Large.Inverse</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="seekBarStyle">@style/Widget.DeviceDefault.SeekBar</item>
<item name="ratingBarStyle">@style/Widget.DeviceDefault.RatingBar</item>
<item name="ratingBarStyleIndicator">@style/Widget.DeviceDefault.RatingBar.Indicator</item>
@@ -351,7 +351,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -468,7 +468,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -587,7 +587,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -705,7 +705,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -831,7 +831,7 @@
<item name="alertDialogTheme">@style/Theme.DeviceDefault.Dialog.Alert</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -948,7 +948,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -1064,7 +1064,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -1181,7 +1181,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -1314,7 +1314,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -1432,7 +1432,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -1548,7 +1548,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -1666,7 +1666,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -1783,7 +1783,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -1900,7 +1900,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -2017,7 +2017,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -2134,7 +2134,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -2251,7 +2251,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -2373,7 +2373,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -2488,7 +2488,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -2642,7 +2642,7 @@
<item name="progressBarStyleSmallInverse">@style/Widget.DeviceDefault.Light.ProgressBar.Small.Inverse</item>
<item name="progressBarStyleLargeInverse">@style/Widget.DeviceDefault.Light.ProgressBar.Large.Inverse</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="seekBarStyle">@style/Widget.DeviceDefault.Light.SeekBar</item>
<item name="ratingBarStyle">@style/Widget.DeviceDefault.Light.RatingBar</item>
<item name="ratingBarStyleIndicator">@style/Widget.DeviceDefault.Light.RatingBar.Indicator</item>
@@ -2858,7 +2858,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -2974,7 +2974,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -3091,7 +3091,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -3210,7 +3210,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -3328,7 +3328,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -3452,7 +3452,7 @@
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -3572,7 +3572,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -3691,7 +3691,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -3811,7 +3811,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -4133,7 +4133,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -4254,7 +4254,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -4373,7 +4373,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -4491,7 +4491,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -4608,7 +4608,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -4725,7 +4725,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -4840,7 +4840,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -5066,7 +5066,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -5162,7 +5162,7 @@
<item name="alertDialogTheme">@style/Theme.DeviceDefault.Light.Dialog.Alert</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -5280,7 +5280,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -5471,7 +5471,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -5522,7 +5522,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -5641,7 +5641,7 @@
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
diff --git a/core/tests/GameManagerTests/Android.bp b/core/tests/GameManagerTests/Android.bp
index 0e3bc65..a252f8b 100644
--- a/core/tests/GameManagerTests/Android.bp
+++ b/core/tests/GameManagerTests/Android.bp
@@ -37,3 +37,10 @@
certificate: "platform",
test_suites: ["device-tests"],
}
+
+test_module_config {
+ name: "FrameworksCoreGameManagerTests_android_app",
+ base: "FrameworksCoreGameManagerTests",
+ test_suites: ["device-tests"],
+ include_filters: ["android.app"],
+}
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index b0e48f1..99cbf05 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -21,6 +21,7 @@
srcs: [
"DisabledTestApp/src/**/*.java",
"EnabledTestApp/src/**/*.java",
+ "BinderFrozenStateChangeCallbackTestApp/src/**/*.java",
"BinderProxyCountingTestApp/src/**/*.java",
"BinderProxyCountingTestService/src/**/*.java",
"BinderDeathRecipientHelperApp/src/**/*.java",
@@ -138,6 +139,7 @@
":BinderDeathRecipientHelperApp1",
":BinderDeathRecipientHelperApp2",
":com.android.cts.helpers.aosp",
+ ":BinderFrozenStateChangeCallbackTestApp",
":BinderProxyCountingTestApp",
":BinderProxyCountingTestService",
":AppThatUsesAppOps",
diff --git a/core/tests/coretests/AndroidTest.xml b/core/tests/coretests/AndroidTest.xml
index 99b73a4..b1f1e2c 100644
--- a/core/tests/coretests/AndroidTest.xml
+++ b/core/tests/coretests/AndroidTest.xml
@@ -22,6 +22,7 @@
<option name="test-file-name" value="FrameworksCoreTests.apk" />
<option name="test-file-name" value="BinderDeathRecipientHelperApp1.apk" />
<option name="test-file-name" value="BinderDeathRecipientHelperApp2.apk" />
+ <option name="test-file-name" value="BinderFrozenStateChangeCallbackTestApp.apk" />
<option name="test-file-name" value="BinderProxyCountingTestApp.apk" />
<option name="test-file-name" value="BinderProxyCountingTestService.apk" />
<option name="test-file-name" value="AppThatUsesAppOps.apk" />
diff --git a/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/Android.bp b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/Android.bp
new file mode 100644
index 0000000..de97dda
--- /dev/null
+++ b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/Android.bp
@@ -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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+ name: "BinderFrozenStateChangeCallbackTestApp",
+
+ static_libs: ["coretests-aidl"],
+ srcs: ["**/*.java"],
+
+ platform_apis: true,
+ certificate: "platform",
+
+ test_suites: ["device-tests"],
+}
diff --git a/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/AndroidManifest.xml b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/AndroidManifest.xml
new file mode 100644
index 0000000..29c8f55
--- /dev/null
+++ b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.coretests.bfscctestapp">
+
+ <application>
+ <service android:name=".BfsccTestAppCmdService"
+ android:exported="true"/>
+ </application>
+</manifest>
diff --git a/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java
new file mode 100644
index 0000000..77e8a40
--- /dev/null
+++ b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java
@@ -0,0 +1,71 @@
+/*
+ * 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.frameworks.coretests.bfscctestapp;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.android.frameworks.coretests.aidl.IBfsccTestAppCmdService;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+public class BfsccTestAppCmdService extends Service {
+ private IBfsccTestAppCmdService.Stub mBinder = new IBfsccTestAppCmdService.Stub() {
+ private final LinkedBlockingQueue<IBinder.IFrozenStateChangeCallback.State> mNotifications =
+ new LinkedBlockingQueue<>();
+
+ @Override
+ public void listenTo(IBinder binder) throws RemoteException {
+ binder.addFrozenStateChangeCallback(
+ (IBinder who, IBinder.IFrozenStateChangeCallback.State state)
+ -> mNotifications.offer(state));
+ }
+
+ @Override
+ public boolean[] waitAndConsumeNotifications() {
+ List<Boolean> results = new ArrayList<>();
+ try {
+ IBinder.IFrozenStateChangeCallback.State state =
+ mNotifications.poll(5, TimeUnit.SECONDS);
+ if (state != null) {
+ results.add(state == IBinder.IFrozenStateChangeCallback.State.FROZEN);
+ }
+ } catch (InterruptedException e) {
+ return null;
+ }
+ while (mNotifications.size() > 0) {
+ results.add(mNotifications.poll()
+ == IBinder.IFrozenStateChangeCallback.State.FROZEN);
+ }
+ boolean[] convertedResults = new boolean[results.size()];
+ for (int i = 0; i < results.size(); i++) {
+ convertedResults[i] = results.get(i).booleanValue();
+ }
+ return convertedResults;
+ }
+ };
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+}
diff --git a/core/tests/coretests/BinderProxyCountingTestService/src/com/android/frameworks/coretests/binderproxycountingtestservice/BinderProxyCountingService.java b/core/tests/coretests/BinderProxyCountingTestService/src/com/android/frameworks/coretests/binderproxycountingtestservice/BinderProxyCountingService.java
index 41b4c69..09d79a6 100644
--- a/core/tests/coretests/BinderProxyCountingTestService/src/com/android/frameworks/coretests/binderproxycountingtestservice/BinderProxyCountingService.java
+++ b/core/tests/coretests/BinderProxyCountingTestService/src/com/android/frameworks/coretests/binderproxycountingtestservice/BinderProxyCountingService.java
@@ -50,4 +50,4 @@
public IBinder onBind(Intent intent) {
return mBinder;
}
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java b/core/tests/coretests/aidl/com/android/frameworks/coretests/aidl/IBfsccTestAppCmdService.aidl
similarity index 71%
copy from services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
copy to core/tests/coretests/aidl/com/android/frameworks/coretests/aidl/IBfsccTestAppCmdService.aidl
index 502337c..d8d7dc4 100644
--- a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
+++ b/core/tests/coretests/aidl/com/android/frameworks/coretests/aidl/IBfsccTestAppCmdService.aidl
@@ -14,11 +14,9 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.frameworks.coretests.aidl;
-class BinaryStatePowerStatsLayout extends EnergyConsumerPowerStatsLayout {
- BinaryStatePowerStatsLayout() {
- addDeviceSectionUsageDuration();
- addUidSectionUsageDuration();
- }
+interface IBfsccTestAppCmdService {
+ void listenTo(IBinder binder);
+ boolean[] waitAndConsumeNotifications();
}
diff --git a/core/tests/coretests/src/android/app/NotificationChannelTest.java b/core/tests/coretests/src/android/app/NotificationChannelTest.java
index c08e42b..e47ef2d 100644
--- a/core/tests/coretests/src/android/app/NotificationChannelTest.java
+++ b/core/tests/coretests/src/android/app/NotificationChannelTest.java
@@ -233,6 +233,33 @@
}
@Test
+ @EnableFlags({Flags.FLAG_NOTIFICATION_CHANNEL_VIBRATION_EFFECT_API,
+ Flags.FLAG_NOTIF_CHANNEL_CROP_VIBRATION_EFFECTS})
+ public void testLongVibrationFields_canWriteToXml() throws Exception {
+ NotificationChannel channel = new NotificationChannel("id", "name", 3);
+ // populate pattern with contents
+ long[] pattern = new long[65550 / 2];
+ for (int i = 0; i < pattern.length; i++) {
+ pattern[i] = 100;
+ }
+ channel.setVibrationPattern(pattern); // with flag on, also sets effect
+
+ // Send it through parceling & unparceling to simulate being passed through a binder call
+ NotificationChannel fromParcel = writeToAndReadFromParcel(channel);
+ assertThat(fromParcel.getVibrationPattern().length).isEqualTo(
+ NotificationChannel.MAX_VIBRATION_LENGTH);
+
+ // Confirm that this also survives writing to & restoring from XML
+ NotificationChannel result = backUpAndRestore(fromParcel);
+ assertThat(result.getVibrationPattern().length).isEqualTo(
+ NotificationChannel.MAX_VIBRATION_LENGTH);
+ assertThat(result.getVibrationEffect()).isNotNull();
+ assertThat(result.getVibrationEffect()
+ .computeCreateWaveformOffOnTimingsOrNull())
+ .isEqualTo(result.getVibrationPattern());
+ }
+
+ @Test
public void testRestoreSoundUri_customLookup() throws Exception {
Uri uriToBeRestoredUncanonicalized = Uri.parse("content://media/1");
Uri uriToBeRestoredCanonicalized = Uri.parse("content://media/1?title=Song&canonical=1");
diff --git a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
index 10aed8d..1429272 100644
--- a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
+++ b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
@@ -16,8 +16,6 @@
package android.graphics;
-import static com.android.text.flags.Flags.FLAG_VENDOR_CUSTOM_LOCALE_FALLBACK;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -32,7 +30,6 @@
import android.graphics.fonts.SystemFonts;
import android.graphics.text.PositionedGlyphs;
import android.graphics.text.TextRunShaper;
-import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.text.FontConfig;
@@ -931,7 +928,6 @@
return String.format(xml, op, lang, font);
}
- @RequiresFlagsEnabled(FLAG_VENDOR_CUSTOM_LOCALE_FALLBACK)
@Test
public void testBuildSystemFallback__Customization_locale_prepend() {
final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
@@ -947,7 +943,6 @@
assertB3emFontIsUsed(typeface);
}
- @RequiresFlagsEnabled(FLAG_VENDOR_CUSTOM_LOCALE_FALLBACK)
@Test
public void testBuildSystemFallback__Customization_locale_replace() {
final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
@@ -963,7 +958,6 @@
assertB3emFontIsUsed(typeface);
}
- @RequiresFlagsEnabled(FLAG_VENDOR_CUSTOM_LOCALE_FALLBACK)
@Test
public void testBuildSystemFallback__Customization_locale_append() {
final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
@@ -979,7 +973,6 @@
assertA3emFontIsUsed(typeface);
}
- @RequiresFlagsEnabled(FLAG_VENDOR_CUSTOM_LOCALE_FALLBACK)
@Test
public void testBuildSystemFallback__Customization_locale_ScriptMismatch() {
final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
@@ -995,7 +988,6 @@
assertA3emFontIsUsed(typeface);
}
- @RequiresFlagsEnabled(FLAG_VENDOR_CUSTOM_LOCALE_FALLBACK)
@Test
public void testBuildSystemFallback__Customization_locale_SubscriptMatch() {
final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
diff --git a/core/tests/coretests/src/android/os/BinderFrozenStateChangeNotificationTest.java b/core/tests/coretests/src/android/os/BinderFrozenStateChangeNotificationTest.java
new file mode 100644
index 0000000..ee2e7e0
--- /dev/null
+++ b/core/tests/coretests/src/android/os/BinderFrozenStateChangeNotificationTest.java
@@ -0,0 +1,267 @@
+/*
+ * 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.os;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
+
+import com.android.frameworks.coretests.aidl.IBfsccTestAppCmdService;
+import com.android.frameworks.coretests.bdr_helper_app.TestCommsReceiver;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Queue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Tests functionality of {@link android.os.IBinder.IFrozenStateChangeCallback}.
+ */
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = ActivityManager.class)
+public class BinderFrozenStateChangeNotificationTest {
+ private static final String TAG = BinderFrozenStateChangeNotificationTest.class.getSimpleName();
+
+ private static final String TEST_PACKAGE_NAME_1 =
+ "com.android.frameworks.coretests.bfscctestapp";
+ private static final String TEST_PACKAGE_NAME_2 =
+ "com.android.frameworks.coretests.bdr_helper_app1";
+ private static final String TEST_APP_CMD_SERVICE =
+ TEST_PACKAGE_NAME_1 + ".BfsccTestAppCmdService";
+
+ private static final int CALLBACK_WAIT_TIMEOUT_SECS = 5;
+
+ private IBfsccTestAppCmdService mBfsccTestAppCmdService;
+ private ServiceConnection mTestAppConnection;
+ private Context mContext;
+ private Handler mHandler;
+
+ @Rule
+ public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mHandler = new Handler(Looper.getMainLooper());
+ ((ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE)).killUid(
+ mContext.getPackageManager().getPackageUid(TEST_PACKAGE_NAME_1, 0),
+ "Wiping Test Package");
+ mTestAppConnection = bindService();
+ }
+
+ private IBinder getNewRemoteBinder(String testPackage) throws InterruptedException {
+ final CountDownLatch resultLatch = new CountDownLatch(1);
+ final AtomicInteger resultCode = new AtomicInteger(Activity.RESULT_CANCELED);
+ final AtomicReference<Bundle> resultExtras = new AtomicReference<>();
+
+ final Intent intent = new Intent(TestCommsReceiver.ACTION_GET_BINDER)
+ .setClassName(testPackage, TestCommsReceiver.class.getName());
+ mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ resultCode.set(getResultCode());
+ resultExtras.set(getResultExtras(true));
+ resultLatch.countDown();
+ }
+ }, mHandler, Activity.RESULT_CANCELED, null, null);
+
+ assertTrue("Request for binder timed out", resultLatch.await(5, TimeUnit.SECONDS));
+ assertEquals(Activity.RESULT_OK, resultCode.get());
+ return resultExtras.get().getBinder(TestCommsReceiver.EXTRA_KEY_BINDER);
+ }
+
+ private ServiceConnection bindService()
+ throws Exception {
+ final CountDownLatch bindLatch = new CountDownLatch(1);
+ ServiceConnection connection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ Log.i(TAG, "Service connected");
+ mBfsccTestAppCmdService = IBfsccTestAppCmdService.Stub.asInterface(service);
+ bindLatch.countDown();
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ Log.i(TAG, "Service disconnected");
+ }
+ };
+ mContext.bindService(
+ new Intent().setComponent(
+ new ComponentName(TEST_PACKAGE_NAME_1, TEST_APP_CMD_SERVICE)),
+ connection,
+ Context.BIND_AUTO_CREATE
+ | Context.BIND_NOT_FOREGROUND);
+ if (!bindLatch.await(5, TimeUnit.SECONDS)) {
+ fail("Timed out waiting for the service to bind");
+ }
+ return connection;
+ }
+
+ private void unbindService(ServiceConnection service) {
+ if (service != null) {
+ mContext.unbindService(service);
+ }
+ }
+
+ @Test
+ public void onStateChangeCalled() throws Exception {
+ final LinkedBlockingQueue<Boolean> results = new LinkedBlockingQueue<>();
+ if (createCallback(mBfsccTestAppCmdService.asBinder(), results) == null) {
+ return;
+ }
+ ensureUnfrozenCallback(results);
+ freezeApp1();
+ ensureFrozenCallback(results);
+ unfreezeApp1();
+ ensureUnfrozenCallback(results);
+ }
+
+ @Test
+ public void onStateChangeNotCalledAfterCallbackRemoved() throws Exception {
+ final LinkedBlockingQueue<Boolean> results = new LinkedBlockingQueue<>();
+ IBinder.IFrozenStateChangeCallback callback;
+ if ((callback = createCallback(mBfsccTestAppCmdService.asBinder(), results)) == null) {
+ return;
+ }
+ ensureUnfrozenCallback(results);
+ mBfsccTestAppCmdService.asBinder().removeFrozenStateChangeCallback(callback);
+ freezeApp1();
+ assertEquals("No more callbacks should be invoked.", 0, results.size());
+ }
+
+ @Test
+ public void multipleCallbacks() throws Exception {
+ final LinkedBlockingQueue<Boolean> results1 = new LinkedBlockingQueue<>();
+ final LinkedBlockingQueue<Boolean> results2 = new LinkedBlockingQueue<>();
+ IBinder.IFrozenStateChangeCallback callback1;
+ if ((callback1 = createCallback(mBfsccTestAppCmdService.asBinder(), results1)) == null) {
+ return;
+ }
+ ensureUnfrozenCallback(results1);
+ freezeApp1();
+ ensureFrozenCallback(results1);
+ if (createCallback(mBfsccTestAppCmdService.asBinder(), results2) == null) {
+ return;
+ }
+ ensureFrozenCallback(results2);
+
+ unfreezeApp1();
+ ensureUnfrozenCallback(results1);
+ ensureUnfrozenCallback(results2);
+
+ mBfsccTestAppCmdService.asBinder().removeFrozenStateChangeCallback(callback1);
+ freezeApp1();
+ assertEquals("No more callbacks should be invoked.", 0, results1.size());
+ ensureFrozenCallback(results2);
+ }
+
+ @Test
+ public void onStateChangeCalledWithTheRightBinder() throws Exception {
+ final IBinder binder = mBfsccTestAppCmdService.asBinder();
+ final LinkedBlockingQueue<IBinder> results = new LinkedBlockingQueue<>();
+ IBinder.IFrozenStateChangeCallback callback =
+ (IBinder who, IBinder.IFrozenStateChangeCallback.State state) -> results.offer(who);
+ try {
+ binder.addFrozenStateChangeCallback(callback);
+ } catch (UnsupportedOperationException e) {
+ return;
+ }
+ assertEquals("Callback received the wrong Binder object.",
+ binder, results.poll(CALLBACK_WAIT_TIMEOUT_SECS, TimeUnit.SECONDS));
+ freezeApp1();
+ assertEquals("Callback received the wrong Binder object.",
+ binder, results.poll(CALLBACK_WAIT_TIMEOUT_SECS, TimeUnit.SECONDS));
+ unfreezeApp1();
+ assertEquals("Callback received the wrong Binder object.",
+ binder, results.poll(CALLBACK_WAIT_TIMEOUT_SECS, TimeUnit.SECONDS));
+ }
+
+ @After
+ public void tearDown() {
+ if (mTestAppConnection != null) {
+ mContext.unbindService(mTestAppConnection);
+ }
+ }
+
+ private IBinder.IFrozenStateChangeCallback createCallback(IBinder binder, Queue<Boolean> queue)
+ throws RemoteException {
+ try {
+ final IBinder.IFrozenStateChangeCallback callback =
+ (IBinder who, IBinder.IFrozenStateChangeCallback.State state) ->
+ queue.offer(state == IBinder.IFrozenStateChangeCallback.State.FROZEN);
+ binder.addFrozenStateChangeCallback(callback);
+ return callback;
+ } catch (UnsupportedOperationException e) {
+ return null;
+ }
+ }
+
+ private void ensureFrozenCallback(LinkedBlockingQueue<Boolean> queue)
+ throws InterruptedException {
+ assertEquals(Boolean.TRUE, queue.poll(CALLBACK_WAIT_TIMEOUT_SECS, TimeUnit.SECONDS));
+ }
+
+ private void ensureUnfrozenCallback(LinkedBlockingQueue<Boolean> queue)
+ throws InterruptedException {
+ assertEquals(Boolean.FALSE, queue.poll(CALLBACK_WAIT_TIMEOUT_SECS, TimeUnit.SECONDS));
+ }
+
+ private String executeShellCommand(String cmd) throws Exception {
+ return UiDevice.getInstance(
+ InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd);
+ }
+
+ private void freezeApp1() throws Exception {
+ executeShellCommand("am freeze " + TEST_PACKAGE_NAME_1);
+ }
+
+ private void freezeApp2() throws Exception {
+ executeShellCommand("am freeze " + TEST_PACKAGE_NAME_2);
+ }
+
+ private void unfreezeApp1() throws Exception {
+ executeShellCommand("am unfreeze " + TEST_PACKAGE_NAME_1);
+ }
+
+ private void unfreezeApp2() throws Exception {
+ executeShellCommand("am unfreeze " + TEST_PACKAGE_NAME_2);
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
index 499caf5..c3a5b19c94 100644
--- a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
@@ -359,7 +359,7 @@
tracker.end(FrameTracker.REASON_END_NORMAL);
// Send incomplete callback for 102L
- sendSfFrame(tracker, 102L, JANK_NONE);
+ sendSfFrame(tracker, 4, 102L, JANK_NONE);
// Send janky but complete callbck fo 103L
sendFrame(tracker, 50, JANK_APP_DEADLINE_MISSED, 103L);
@@ -629,7 +629,7 @@
if (!tracker.mSurfaceOnly) {
sendHwuiFrame(tracker, durationMillis, vsyncId, firstWindowFrame);
}
- sendSfFrame(tracker, vsyncId, jankType);
+ sendSfFrame(tracker, durationMillis, vsyncId, jankType);
}
private void sendHwuiFrame(FrameTracker tracker, long durationMillis, long vsyncId,
@@ -645,11 +645,13 @@
captor.getValue().run();
}
- private void sendSfFrame(FrameTracker tracker, long vsyncId, @JankType int jankType) {
+ private void sendSfFrame(
+ FrameTracker tracker, long durationMillis, long vsyncId, @JankType int jankType) {
final ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
doNothing().when(tracker).postCallback(captor.capture());
mListenerCapture.getValue().onJankDataAvailable(new JankData[] {
- new JankData(vsyncId, jankType, FRAME_TIME_60Hz)
+ new JankData(vsyncId, jankType, FRAME_TIME_60Hz, FRAME_TIME_60Hz,
+ TimeUnit.MILLISECONDS.toNanos(durationMillis))
});
captor.getValue().run();
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java b/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java
index 66de3d7..397cdcf 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java
@@ -124,6 +124,16 @@
return this;
}
+ @Override
+ public void addFrozenStateChangeCallback(IFrozenStateChangeCallback callback)
+ throws RemoteException {
+ }
+
+ @Override
+ public boolean removeFrozenStateChangeCallback(IFrozenStateChangeCallback callback) {
+ return false;
+ }
+
public void die() {
isAlive = false;
if (mRecipient != null) {
diff --git a/core/tests/hdmitests/Android.bp b/core/tests/hdmitests/Android.bp
index 5f6eaf9..e11bc55 100644
--- a/core/tests/hdmitests/Android.bp
+++ b/core/tests/hdmitests/Android.bp
@@ -37,3 +37,10 @@
certificate: "platform",
test_suites: ["device-tests"],
}
+
+test_module_config {
+ name: "HdmiCecTests_hardware_hdmi",
+ base: "HdmiCecTests",
+ test_suites: ["device-tests"],
+ include_filters: ["android.hardware.hdmi"],
+}
diff --git a/core/tests/mockingcoretests/Android.bp b/core/tests/mockingcoretests/Android.bp
index aca52a8..7fd813a 100644
--- a/core/tests/mockingcoretests/Android.bp
+++ b/core/tests/mockingcoretests/Android.bp
@@ -63,3 +63,13 @@
certificate: "platform",
}
+
+test_module_config {
+ name: "FrameworksMockingCoreTests_os_bundlerecyclingtest",
+ base: "FrameworksMockingCoreTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["android.os.BundleRecyclingTest"],
+}
diff --git a/core/tests/timetests/Android.bp b/core/tests/timetests/Android.bp
index 51181a8..c33d5ee 100644
--- a/core/tests/timetests/Android.bp
+++ b/core/tests/timetests/Android.bp
@@ -23,3 +23,17 @@
certificate: "platform",
test_suites: ["device-tests"],
}
+
+test_module_config {
+ name: "FrameworksTimeCoreTests_android_app",
+ base: "FrameworksTimeCoreTests",
+ test_suites: ["device-tests"],
+ include_filters: ["android.app."],
+}
+
+test_module_config {
+ name: "FrameworksTimeCoreTests_android_service",
+ base: "FrameworksTimeCoreTests",
+ test_suites: ["device-tests"],
+ include_filters: ["android.service."],
+}
diff --git a/core/tests/vibrator/src/android/os/VibrationEffectTest.java b/core/tests/vibrator/src/android/os/VibrationEffectTest.java
index 4f76dd6..f5b04ee 100644
--- a/core/tests/vibrator/src/android/os/VibrationEffectTest.java
+++ b/core/tests/vibrator/src/android/os/VibrationEffectTest.java
@@ -430,6 +430,86 @@
}
@Test
+ public void cropToLength_waveform_underLength() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[]{0, 1, 2},
+ /* repeatIndex= */ -1);
+ VibrationEffect result = effect.cropToLengthOrNull(5);
+
+ assertThat(result).isEqualTo(effect); // unchanged
+ }
+
+ @Test
+ public void cropToLength_waveform_overLength() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[]{0, 1, 2, 3, 4, 5, 6},
+ /* repeatIndex= */ -1);
+ VibrationEffect result = effect.cropToLengthOrNull(4);
+
+ assertThat(result).isEqualTo(VibrationEffect.createWaveform(
+ new long[]{0, 1, 2, 3},
+ -1));
+ }
+
+ @Test
+ public void cropToLength_waveform_repeating() {
+ // repeating waveforms cannot be truncated
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[]{0, 1, 2, 3, 4, 5, 6},
+ /* repeatIndex= */ 2);
+ VibrationEffect result = effect.cropToLengthOrNull(3);
+
+ assertThat(result).isNull();
+ }
+
+ @Test
+ public void cropToLength_waveform_withAmplitudes() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[]{0, 1, 2, 3, 4, 5, 6},
+ /* amplitudes= */ new int[]{10, 20, 40, 10, 20, 40, 10},
+ /* repeatIndex= */ -1);
+ VibrationEffect result = effect.cropToLengthOrNull(3);
+
+ assertThat(result).isEqualTo(VibrationEffect.createWaveform(
+ new long[]{0, 1, 2},
+ new int[]{10, 20, 40},
+ -1));
+ }
+
+ @Test
+ public void cropToLength_composed() {
+ VibrationEffect effect = VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
+ .compose();
+ VibrationEffect result = effect.cropToLengthOrNull(1);
+
+ assertThat(result).isNotNull();
+ assertThat(result).isEqualTo(VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .compose());
+ }
+
+ @Test
+ public void cropToLength_composed_repeating() {
+ VibrationEffect effect = VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .repeatEffectIndefinitely(TEST_ONE_SHOT)
+ .compose();
+ assertThat(effect.cropToLengthOrNull(1)).isNull();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS)
+ public void cropToLength_vendorEffect() {
+ PersistableBundle vendorData = new PersistableBundle();
+ vendorData.putInt("key", 1);
+ VibrationEffect effect = VibrationEffect.createVendorEffect(vendorData);
+
+ assertThat(effect.cropToLengthOrNull(2)).isNull();
+ }
+
+ @Test
public void getRingtones_noPrebakedRingtones() {
Resources r = mockRingtoneResources(new String[0]);
Context context = mockContext(r);
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 9a55b80..880f30c 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -580,6 +580,11 @@
<permission name="android.permission.PREPARE_FACTORY_RESET" />
<!-- Permission required for CTS test - FileIntegrityManagerTest -->
<permission name="android.permission.SETUP_FSVERITY" />
+ <!-- Permissions required for CTS test - AppFunctionManagerTest -->
+ <permission name="android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED" />
+ <permission name="android.permission.EXECUTE_APP_FUNCTIONS" />
+ <!-- Permission required for CTS test - CtsNfcTestCases -->
+ <permission name="android.permission.NFC_SET_CONTROLLER_ALWAYS_ON" />
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/graphics/java/android/graphics/fonts/FontCustomizationParser.java b/graphics/java/android/graphics/fonts/FontCustomizationParser.java
index ba5628c..b7bf055 100644
--- a/graphics/java/android/graphics/fonts/FontCustomizationParser.java
+++ b/graphics/java/android/graphics/fonts/FontCustomizationParser.java
@@ -182,10 +182,8 @@
// For ignoring the customization, consume the new-locale-family element but don't
// register any customizations.
- if (com.android.text.flags.Flags.vendorCustomLocaleFallback()) {
- outCustomization.add(new FontConfig.Customization.LocaleFallback(
- Locale.forLanguageTag(lang), intOp, family));
- }
+ outCustomization.add(new FontConfig.Customization.LocaleFallback(
+ Locale.forLanguageTag(lang), intOp, family));
} else {
throw new IllegalArgumentException("Unknown customizationType=" + customizationType);
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
index 0726624..bfccb29 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
@@ -16,16 +16,26 @@
package androidx.window.extensions.embedding;
+import static android.window.TaskFragmentOrganizer.KEY_RESTORE_TASK_FRAGMENTS_INFO;
+import static android.window.TaskFragmentOrganizer.KEY_RESTORE_TASK_FRAGMENT_PARENT_INFO;
+
import android.os.Build;
import android.os.Bundle;
+import android.os.IBinder;
import android.os.Looper;
import android.os.MessageQueue;
+import android.util.ArrayMap;
import android.util.Log;
+import android.util.SparseArray;
+import android.window.TaskFragmentInfo;
+import android.window.TaskFragmentParentInfo;
+import android.window.WindowContainerTransaction;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
/**
* Helper class to back up and restore the TaskFragmentOrganizer state, in order to resume
@@ -40,11 +50,21 @@
@NonNull
private final SplitController mController;
@NonNull
+ private final SplitPresenter mPresenter;
+ @NonNull
private final BackupIdler mBackupIdler = new BackupIdler();
private boolean mBackupIdlerScheduled;
- BackupHelper(@NonNull SplitController splitController, @NonNull Bundle savedState) {
+ private final List<ParcelableTaskContainerData> mParcelableTaskContainerDataList =
+ new ArrayList<>();
+ private final ArrayMap<IBinder, TaskFragmentInfo> mTaskFragmentInfos = new ArrayMap<>();
+ private final SparseArray<TaskFragmentParentInfo> mTaskFragmentParentInfos =
+ new SparseArray<>();
+
+ BackupHelper(@NonNull SplitController splitController, @NonNull SplitPresenter splitPresenter,
+ @NonNull Bundle savedState) {
mController = splitController;
+ mPresenter = splitPresenter;
if (!savedState.isEmpty()) {
restoreState(savedState);
@@ -58,7 +78,7 @@
void scheduleBackup() {
if (!mBackupIdlerScheduled) {
mBackupIdlerScheduled = true;
- Looper.myQueue().addIdleHandler(mBackupIdler);
+ Looper.getMainLooper().getQueue().addIdleHandler(mBackupIdler);
}
}
@@ -67,13 +87,13 @@
public boolean queueIdle() {
synchronized (mController.mLock) {
mBackupIdlerScheduled = false;
- startBackup();
+ saveState();
}
return false;
}
}
- private void startBackup() {
+ private void saveState() {
final List<TaskContainer> taskContainers = mController.getTaskContainers();
if (taskContainers.isEmpty()) {
Log.w(TAG, "No task-container to back up");
@@ -97,13 +117,92 @@
return;
}
- final List<ParcelableTaskContainerData> parcelableTaskContainerDataList =
- savedState.getParcelableArrayList(KEY_TASK_CONTAINERS,
- ParcelableTaskContainerData.class);
- for (ParcelableTaskContainerData data : parcelableTaskContainerDataList) {
- final TaskContainer taskContainer = new TaskContainer(data, mController);
- if (DEBUG) Log.d(TAG, "Restoring task " + taskContainer.getTaskId());
- // TODO(b/289875940): implement the TaskContainer restoration.
+ if (DEBUG) Log.d(TAG, "Start restoring saved-state");
+ mParcelableTaskContainerDataList.addAll(savedState.getParcelableArrayList(
+ KEY_TASK_CONTAINERS, ParcelableTaskContainerData.class));
+ if (DEBUG) Log.d(TAG, "Retrieved tasks : " + mParcelableTaskContainerDataList.size());
+ if (mParcelableTaskContainerDataList.isEmpty()) {
+ return;
+ }
+
+ final List<TaskFragmentInfo> infos = savedState.getParcelableArrayList(
+ KEY_RESTORE_TASK_FRAGMENTS_INFO, TaskFragmentInfo.class);
+ for (TaskFragmentInfo info : infos) {
+ if (DEBUG) Log.d(TAG, "Retrieved: " + info);
+ mTaskFragmentInfos.put(info.getFragmentToken(), info);
+ mPresenter.updateTaskFragmentInfo(info);
+ }
+
+ final List<TaskFragmentParentInfo> parentInfos = savedState.getParcelableArrayList(
+ KEY_RESTORE_TASK_FRAGMENT_PARENT_INFO,
+ TaskFragmentParentInfo.class);
+ for (TaskFragmentParentInfo info : parentInfos) {
+ if (DEBUG) Log.d(TAG, "Retrieved: " + info);
+ mTaskFragmentParentInfos.put(info.getTaskId(), info);
}
}
-}
+
+ boolean hasPendingStateToRestore() {
+ return !mParcelableTaskContainerDataList.isEmpty();
+ }
+
+ /**
+ * Returns {@code true} if any of the {@link TaskContainer} is restored.
+ * Otherwise, returns {@code false}.
+ */
+ boolean rebuildTaskContainers(@NonNull WindowContainerTransaction wct,
+ @NonNull Set<EmbeddingRule> rules) {
+ if (mParcelableTaskContainerDataList.isEmpty()) {
+ return false;
+ }
+
+ if (DEBUG) Log.d(TAG, "Rebuilding TaskContainers.");
+ final ArrayMap<String, EmbeddingRule> embeddingRuleMap = new ArrayMap<>();
+ for (EmbeddingRule rule : rules) {
+ embeddingRuleMap.put(rule.getTag(), rule);
+ }
+
+ boolean restoredAny = false;
+ for (int i = mParcelableTaskContainerDataList.size() - 1; i >= 0; i--) {
+ final ParcelableTaskContainerData parcelableTaskContainerData =
+ mParcelableTaskContainerDataList.get(i);
+ final List<String> tags = parcelableTaskContainerData.getSplitRuleTags();
+ if (!embeddingRuleMap.containsAll(tags)) {
+ // has unknown tag, unable to restore.
+ if (DEBUG) {
+ Log.d(TAG, "Rebuilding TaskContainer abort! Unknown Tag. Task#"
+ + parcelableTaskContainerData.mTaskId);
+ }
+ continue;
+ }
+
+ mParcelableTaskContainerDataList.remove(parcelableTaskContainerData);
+ final TaskContainer taskContainer = new TaskContainer(parcelableTaskContainerData,
+ mController, mTaskFragmentInfos);
+ if (DEBUG) Log.d(TAG, "Created TaskContainer " + taskContainer);
+ mController.addTaskContainer(taskContainer.getTaskId(), taskContainer);
+
+ for (ParcelableSplitContainerData splitData :
+ parcelableTaskContainerData.getParcelableSplitContainerDataList()) {
+ final SplitRule rule = (SplitRule) embeddingRuleMap.get(splitData.mSplitRuleTag);
+ assert rule != null;
+ if (mController.getContainer(splitData.getPrimaryContainerToken()) != null
+ && mController.getContainer(splitData.getSecondaryContainerToken())
+ != null) {
+ taskContainer.addSplitContainer(
+ new SplitContainer(splitData, mController, rule));
+ }
+ }
+
+ mController.onTaskFragmentParentRestored(wct, taskContainer.getTaskId(),
+ mTaskFragmentParentInfos.get(taskContainer.getTaskId()));
+ restoredAny = true;
+ }
+
+ if (mParcelableTaskContainerDataList.isEmpty()) {
+ mTaskFragmentParentInfos.clear();
+ mTaskFragmentInfos.clear();
+ }
+ return restoredAny;
+ }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ParcelableSplitContainerData.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ParcelableSplitContainerData.java
index 817cfce..cb280c5 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ParcelableSplitContainerData.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ParcelableSplitContainerData.java
@@ -89,13 +89,13 @@
};
@NonNull
- private IBinder getPrimaryContainerToken() {
+ IBinder getPrimaryContainerToken() {
return mSplitContainer != null ? mSplitContainer.getPrimaryContainer().getToken()
: mPrimaryContainerToken;
}
@NonNull
- private IBinder getSecondaryContainerToken() {
+ IBinder getSecondaryContainerToken() {
return mSplitContainer != null ? mSplitContainer.getSecondaryContainer().getToken()
: mSecondaryContainerToken;
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ParcelableTaskContainerData.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ParcelableTaskContainerData.java
index 7377d00..97aa699 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ParcelableTaskContainerData.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/ParcelableTaskContainerData.java
@@ -108,6 +108,15 @@
: mParcelableSplitContainerDataList;
}
+ @NonNull
+ List<String> getSplitRuleTags() {
+ final List<String> tags = new ArrayList<>();
+ for (ParcelableSplitContainerData data : getParcelableSplitContainerDataList()) {
+ tags.add(data.mSplitRuleTag);
+ }
+ return tags;
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java
index 6d436ec..faf73c2 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitContainer.java
@@ -86,6 +86,25 @@
}
}
+ /** This is only used when restoring it from a {@link ParcelableSplitContainerData}. */
+ SplitContainer(@NonNull ParcelableSplitContainerData parcelableData,
+ @NonNull SplitController splitController, @NonNull SplitRule splitRule) {
+ mParcelableData = parcelableData;
+ mPrimaryContainer = splitController.getContainer(parcelableData.getPrimaryContainerToken());
+ mSecondaryContainer = splitController.getContainer(
+ parcelableData.getSecondaryContainerToken());
+ mSplitRule = splitRule;
+ mDefaultSplitAttributes = splitRule.getDefaultSplitAttributes();
+ mCurrentSplitAttributes = mDefaultSplitAttributes;
+
+ if (shouldFinishPrimaryWithSecondary(splitRule)) {
+ mSecondaryContainer.addContainerToFinishOnExit(mPrimaryContainer);
+ }
+ if (shouldFinishSecondaryWithPrimary(splitRule)) {
+ mPrimaryContainer.addContainerToFinishOnExit(mSecondaryContainer);
+ }
+ }
+
void setPrimaryContainer(@NonNull TaskFragmentContainer primaryContainer) {
if (!mParcelableData.mIsPrimaryContainerMutable) {
throw new IllegalStateException("Cannot update primary TaskFragmentContainer");
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index f2f2b7ea..db4bb0e 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -279,6 +279,26 @@
Log.i(TAG, "Setting embedding rules. Size: " + rules.size());
mSplitRules.clear();
mSplitRules.addAll(rules);
+
+ if (!Flags.aeBackStackRestore() || !mPresenter.isRebuildTaskContainersNeeded()) {
+ return;
+ }
+
+ try {
+ final TransactionRecord transactionRecord =
+ mTransactionManager.startNewTransaction();
+ final WindowContainerTransaction wct = transactionRecord.getTransaction();
+ if (mPresenter.rebuildTaskContainers(wct, rules)) {
+ transactionRecord.apply(false /* shouldApplyIndependently */);
+ updateCallbackIfNecessary();
+ } else {
+ transactionRecord.abort();
+ }
+ } catch (IllegalStateException ex) {
+ Log.e(TAG, "Having an existing transaction while running restoration with"
+ + "new rules!! It is likely too late to perform the restoration "
+ + "already!?", ex);
+ }
}
}
@@ -903,6 +923,12 @@
}
@GuardedBy("mLock")
+ void onTaskFragmentParentRestored(@NonNull WindowContainerTransaction wct, int taskId,
+ @NonNull TaskFragmentParentInfo parentInfo) {
+ onTaskFragmentParentInfoChanged(wct, taskId, parentInfo);
+ }
+
+ @GuardedBy("mLock")
void updateContainersInTaskIfVisible(@NonNull WindowContainerTransaction wct, int taskId) {
final TaskContainer taskContainer = getTaskContainer(taskId);
if (taskContainer == null) {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index abc7b29..0c0ded9 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -24,6 +24,7 @@
import static androidx.window.extensions.embedding.WindowAttributes.DIM_AREA_ON_TASK;
import android.annotation.AnimRes;
+import android.annotation.NonNull;
import android.app.Activity;
import android.app.ActivityThread;
import android.app.WindowConfiguration;
@@ -47,7 +48,6 @@
import android.window.WindowContainerTransaction;
import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.window.extensions.core.util.function.Function;
import androidx.window.extensions.embedding.SplitAttributes.SplitType;
@@ -67,6 +67,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.Executor;
/**
@@ -174,7 +175,7 @@
} else {
registerOrganizer();
}
- mBackupHelper = new BackupHelper(controller, outSavedState);
+ mBackupHelper = new BackupHelper(controller, this, outSavedState);
if (!SplitController.ENABLE_SHELL_TRANSITIONS) {
// TODO(b/207070762): cleanup with legacy app transition
// Animation will be handled by WM Shell when Shell transition is enabled.
@@ -186,6 +187,15 @@
mBackupHelper.scheduleBackup();
}
+ boolean isRebuildTaskContainersNeeded() {
+ return mBackupHelper.hasPendingStateToRestore();
+ }
+
+ boolean rebuildTaskContainers(@NonNull WindowContainerTransaction wct,
+ @NonNull Set<EmbeddingRule> rules) {
+ return mBackupHelper.rebuildTaskContainers(wct, rules);
+ }
+
/**
* Deletes the specified container and all other associated and dependent containers in the same
* transaction.
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index 82dfda5..74cce68 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -31,6 +31,7 @@
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.IBinder;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -136,6 +137,7 @@
mInfo = new TaskFragmentParentInfo(
taskProperties.getConfiguration(),
taskProperties.getDisplayId(),
+ taskId,
// Note that it is always called when there's a new Activity is started, which
// implies the host task is visible and has an activity in the task.
true /* visible */,
@@ -146,14 +148,23 @@
/** This is only used when restoring it from a {@link ParcelableTaskContainerData}. */
TaskContainer(@NonNull ParcelableTaskContainerData data,
- @NonNull SplitController splitController) {
+ @NonNull SplitController splitController,
+ @NonNull ArrayMap<IBinder, TaskFragmentInfo> taskFragmentInfoMap) {
mParcelableTaskContainerData = new ParcelableTaskContainerData(data, this);
+ mInfo = new TaskFragmentParentInfo(new Configuration(), 0 /* displayId */, -1 /* taskId */,
+ false /* visible */, false /* hasDirectActivity */, null /* decorSurface */);
mSplitController = splitController;
for (ParcelableTaskFragmentContainerData tfData :
data.getParcelableTaskFragmentContainerDataList()) {
- final TaskFragmentContainer container =
- new TaskFragmentContainer(tfData, splitController, this);
- mContainers.add(container);
+ final TaskFragmentInfo info = taskFragmentInfoMap.get(tfData.mToken);
+ if (info != null && !info.isEmpty()) {
+ final TaskFragmentContainer container =
+ new TaskFragmentContainer(tfData, splitController, this);
+ container.setInfo(new WindowContainerTransaction(), info);
+ mContainers.add(container);
+ } else {
+ Log.d(TAG, "Drop " + tfData + " while restoring Task " + data.mTaskId);
+ }
}
}
@@ -194,7 +205,8 @@
void setInvisible() {
mInfo = new TaskFragmentParentInfo(mInfo.getConfiguration(), mInfo.getDisplayId(),
- false /* visible */, mInfo.hasDirectActivity(), mInfo.getDecorSurface());
+ mInfo.getTaskId(), false /* visible */, mInfo.hasDirectActivity(),
+ mInfo.getDecorSurface());
}
boolean hasDirectActivity() {
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
index 90eeb58..5b97e7e 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/OverlayPresentationTest.java
@@ -549,7 +549,7 @@
assertThat(taskContainer.getTaskFragmentContainers()).containsExactly(overlayContainer);
taskContainer.updateTaskFragmentParentInfo(new TaskFragmentParentInfo(Configuration.EMPTY,
- DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */,
+ DEFAULT_DISPLAY, TASK_ID, true /* visible */, false /* hasDirectActivity */,
null /* decorSurface */));
mSplitController.updateOverlayContainer(mTransaction, overlayContainer);
@@ -618,7 +618,8 @@
final TaskContainer.TaskProperties taskProperties = taskContainer.getTaskProperties();
final TaskFragmentParentInfo parentInfo = new TaskFragmentParentInfo(
new Configuration(taskProperties.getConfiguration()), taskProperties.getDisplayId(),
- true /* visible */, false /* hasDirectActivity */, null /* decorSurface */);
+ TASK_ID, true /* visible */, false /* hasDirectActivity */,
+ null /* decorSurface */);
parentInfo.getConfiguration().windowConfiguration.getBounds().offset(10, 10);
mSplitController.onTaskFragmentParentInfoChanged(mTransaction, TASK_ID, parentInfo);
@@ -642,7 +643,8 @@
final TaskContainer.TaskProperties taskProperties = taskContainer.getTaskProperties();
final TaskFragmentParentInfo parentInfo = new TaskFragmentParentInfo(
new Configuration(taskProperties.getConfiguration()), taskProperties.getDisplayId(),
- true /* visible */, false /* hasDirectActivity */, null /* decorSurface */);
+ TASK_ID, true /* visible */, false /* hasDirectActivity */,
+ null /* decorSurface */);
mSplitController.onTaskFragmentParentInfoChanged(mTransaction, TASK_ID, parentInfo);
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
index d852204..0512412 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
@@ -1164,7 +1164,7 @@
public void testOnTransactionReady_taskFragmentParentInfoChanged() {
final TaskFragmentTransaction transaction = new TaskFragmentTransaction();
final TaskFragmentParentInfo parentInfo = new TaskFragmentParentInfo(Configuration.EMPTY,
- DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */,
+ DEFAULT_DISPLAY, TASK_ID, true /* visible */, false /* hasDirectActivity */,
null /* decorSurface */);
transaction.addChange(new TaskFragmentTransaction.Change(
TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED)
@@ -1625,7 +1625,7 @@
final TaskContainer taskContainer = mSplitController.getTaskContainer(TASK_ID);
final Configuration configuration = new Configuration();
final TaskFragmentParentInfo originalInfo = new TaskFragmentParentInfo(configuration,
- DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */,
+ DEFAULT_DISPLAY, TASK_ID, true /* visible */, false /* hasDirectActivity */,
null /* decorSurface */);
mSplitController.onTaskFragmentParentInfoChanged(mock(WindowContainerTransaction.class),
TASK_ID, originalInfo);
@@ -1634,7 +1634,7 @@
// Making a public configuration change while the Task is invisible.
configuration.densityDpi += 100;
final TaskFragmentParentInfo invisibleInfo = new TaskFragmentParentInfo(configuration,
- DEFAULT_DISPLAY, false /* visible */, false /* hasDirectActivity */,
+ DEFAULT_DISPLAY, TASK_ID, false /* visible */, false /* hasDirectActivity */,
null /* decorSurface */);
mSplitController.onTaskFragmentParentInfoChanged(mock(WindowContainerTransaction.class),
TASK_ID, invisibleInfo);
@@ -1646,7 +1646,7 @@
// Updates when Task to become visible
final TaskFragmentParentInfo visibleInfo = new TaskFragmentParentInfo(configuration,
- DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */,
+ DEFAULT_DISPLAY, TASK_ID, true /* visible */, false /* hasDirectActivity */,
null /* decorSurface */);
mSplitController.onTaskFragmentParentInfoChanged(mock(WindowContainerTransaction.class),
TASK_ID, visibleInfo);
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
index 2847232..97f4d07 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
@@ -23,6 +23,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
+import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createTestTaskContainer;
import static org.junit.Assert.assertEquals;
@@ -82,7 +83,7 @@
configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
taskContainer.updateTaskFragmentParentInfo(new TaskFragmentParentInfo(configuration,
- DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */,
+ DEFAULT_DISPLAY, TASK_ID, true /* visible */, false /* hasDirectActivity */,
null /* decorSurface */));
assertEquals(WINDOWING_MODE_MULTI_WINDOW,
@@ -90,7 +91,7 @@
configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
taskContainer.updateTaskFragmentParentInfo(new TaskFragmentParentInfo(configuration,
- DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */,
+ DEFAULT_DISPLAY, TASK_ID, true /* visible */, false /* hasDirectActivity */,
null /* decorSurface */));
assertEquals(WINDOWING_MODE_FREEFORM,
@@ -111,14 +112,14 @@
configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
taskContainer.updateTaskFragmentParentInfo(new TaskFragmentParentInfo(configuration,
- DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */,
+ DEFAULT_DISPLAY, TASK_ID, true /* visible */, false /* hasDirectActivity */,
null /* decorSurface */));
assertFalse(taskContainer.isInPictureInPicture());
configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_PINNED);
taskContainer.updateTaskFragmentParentInfo(new TaskFragmentParentInfo(configuration,
- DEFAULT_DISPLAY, true /* visible */, false /* hasDirectActivity */,
+ DEFAULT_DISPLAY, TASK_ID, true /* visible */, false /* hasDirectActivity */,
null /* decorSurface */));
assertTrue(taskContainer.isInPictureInPicture());
diff --git a/libs/WindowManager/Shell/AndroidManifest.xml b/libs/WindowManager/Shell/AndroidManifest.xml
index bbbc23e..3b739c3 100644
--- a/libs/WindowManager/Shell/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/AndroidManifest.xml
@@ -23,6 +23,7 @@
<uses-permission android:name="android.permission.ROTATE_SURFACE_FLINGER" />
<uses-permission android:name="android.permission.WAKEUP_SURFACE_FLINGER" />
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
+ <uses-permission android:name="android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE" />
<application>
<activity
diff --git a/libs/WindowManager/Shell/aconfig/multitasking.aconfig b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
index 470b7a2..526ccd5 100644
--- a/libs/WindowManager/Shell/aconfig/multitasking.aconfig
+++ b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
@@ -25,11 +25,10 @@
}
flag {
- name: "enable_pip2_implementation"
+ name: "enable_pip2"
namespace: "multitasking"
description: "Enables the new implementation of PiP (PiP2)"
- bug: "290220798"
- is_fixed_read_only: true
+ bug: "311462191"
}
flag {
@@ -145,3 +144,10 @@
description: "Enable an option to move bubbles to fullscreen"
bug: "363326492"
}
+
+flag {
+ name: "enable_flexible_split"
+ namespace: "multitasking"
+ description: "Enables flexibile split feature for split screen"
+ bug: "349828130"
+}
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt
new file mode 100644
index 0000000..35d459f
--- /dev/null
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt
@@ -0,0 +1,324 @@
+/*
+ * 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.bubbles.bar
+
+import android.app.ActivityManager
+import android.content.Context
+import android.graphics.Insets
+import android.graphics.Rect
+import android.view.LayoutInflater
+import android.view.View
+import android.view.WindowManager
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
+import com.android.internal.protolog.ProtoLog
+import com.android.wm.shell.R
+import com.android.wm.shell.bubbles.Bubble
+import com.android.wm.shell.bubbles.BubbleData
+import com.android.wm.shell.bubbles.BubbleExpandedViewManager
+import com.android.wm.shell.bubbles.BubblePositioner
+import com.android.wm.shell.bubbles.BubbleTaskView
+import com.android.wm.shell.bubbles.BubbleTaskViewFactory
+import com.android.wm.shell.bubbles.DeviceConfig
+import com.android.wm.shell.bubbles.RegionSamplingProvider
+import com.android.wm.shell.common.ShellExecutor
+import com.android.wm.shell.shared.bubbles.BubbleBarLocation
+import com.android.wm.shell.shared.handles.RegionSamplingHelper
+import com.android.wm.shell.taskview.TaskView
+import com.android.wm.shell.taskview.TaskViewTaskController
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
+import java.util.Collections
+import java.util.concurrent.Executor
+
+/** Tests for [BubbleBarExpandedViewTest] */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class BubbleBarExpandedViewTest {
+ companion object {
+ const val SCREEN_WIDTH = 2000
+ const val SCREEN_HEIGHT = 1000
+ }
+
+ private val context = ApplicationProvider.getApplicationContext<Context>()
+ private val windowManager = context.getSystemService(WindowManager::class.java)
+
+ private lateinit var mainExecutor: TestExecutor
+ private lateinit var bgExecutor: TestExecutor
+
+ private lateinit var expandedViewManager: BubbleExpandedViewManager
+ private lateinit var positioner: BubblePositioner
+ private lateinit var bubbleTaskView: BubbleTaskView
+
+ private lateinit var bubbleExpandedView: BubbleBarExpandedView
+ private var testableRegionSamplingHelper: TestableRegionSamplingHelper? = null
+ private var regionSamplingProvider: TestRegionSamplingProvider? = null
+
+ @Before
+ fun setUp() {
+ ProtoLog.REQUIRE_PROTOLOGTOOL = false
+ mainExecutor = TestExecutor()
+ bgExecutor = TestExecutor()
+ positioner = BubblePositioner(context, windowManager)
+ positioner.setShowingInBubbleBar(true)
+ val deviceConfig =
+ DeviceConfig(
+ windowBounds = Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT),
+ isLargeScreen = true,
+ isSmallTablet = false,
+ isLandscape = true,
+ isRtl = false,
+ insets = Insets.of(10, 20, 30, 40)
+ )
+ positioner.update(deviceConfig)
+
+ expandedViewManager = createExpandedViewManager()
+ bubbleTaskView = FakeBubbleTaskViewFactory().create()
+
+ val inflater = LayoutInflater.from(context)
+
+ regionSamplingProvider = TestRegionSamplingProvider()
+
+ bubbleExpandedView = (inflater.inflate(
+ R.layout.bubble_bar_expanded_view, null, false /* attachToRoot */
+ ) as BubbleBarExpandedView)
+ bubbleExpandedView.initialize(
+ expandedViewManager,
+ positioner,
+ false /* isOverflow */,
+ bubbleTaskView,
+ mainExecutor,
+ bgExecutor,
+ regionSamplingProvider
+ )
+
+ getInstrumentation().runOnMainSync(Runnable {
+ bubbleExpandedView.onAttachedToWindow()
+ // Helper should be created once attached to window
+ testableRegionSamplingHelper = regionSamplingProvider!!.helper
+ })
+ }
+
+ @After
+ fun tearDown() {
+ testableRegionSamplingHelper?.stopAndDestroy()
+ }
+
+ @Test
+ fun testCreateSamplingHelper_onAttach() {
+ assertThat(testableRegionSamplingHelper).isNotNull()
+ }
+
+ @Test
+ fun testDestroySamplingHelper_onDetach() {
+ bubbleExpandedView.onDetachedFromWindow()
+ assertThat(testableRegionSamplingHelper!!.isDestroyed).isTrue()
+ }
+
+ @Test
+ fun testStopSampling_onDragStart() {
+ bubbleExpandedView.setContentVisibility(true)
+ assertThat(testableRegionSamplingHelper!!.isStarted).isTrue()
+
+ bubbleExpandedView.setDragging(true)
+ assertThat(testableRegionSamplingHelper!!.isStopped).isTrue()
+ }
+
+ @Test
+ fun testStartSampling_onDragEnd() {
+ bubbleExpandedView.setDragging(true)
+ bubbleExpandedView.setContentVisibility(true)
+ assertThat(testableRegionSamplingHelper!!.isStopped).isTrue()
+
+ bubbleExpandedView.setDragging(false)
+ assertThat(testableRegionSamplingHelper!!.isStarted).isTrue()
+ }
+
+ @Test
+ fun testStartSampling_onContentVisible() {
+ bubbleExpandedView.setContentVisibility(true)
+ assertThat(testableRegionSamplingHelper!!.setWindowVisible).isTrue()
+ assertThat(testableRegionSamplingHelper!!.isStarted).isTrue()
+ }
+
+ @Test
+ fun testStopSampling_onContentInvisible() {
+ bubbleExpandedView.setContentVisibility(false)
+
+ assertThat(testableRegionSamplingHelper!!.setWindowInvisible).isTrue()
+ assertThat(testableRegionSamplingHelper!!.isStopped).isTrue()
+ }
+
+ @Test
+ fun testSampling_startStopAnimating_visible() {
+ bubbleExpandedView.isAnimating = true
+ bubbleExpandedView.setContentVisibility(true)
+ assertThat(testableRegionSamplingHelper!!.isStopped).isTrue()
+
+ bubbleExpandedView.isAnimating = false
+ assertThat(testableRegionSamplingHelper!!.isStarted).isTrue()
+ }
+
+ @Test
+ fun testSampling_startStopAnimating_invisible() {
+ bubbleExpandedView.isAnimating = true
+ bubbleExpandedView.setContentVisibility(false)
+ assertThat(testableRegionSamplingHelper!!.isStopped).isTrue()
+ testableRegionSamplingHelper!!.reset()
+
+ bubbleExpandedView.isAnimating = false
+ assertThat(testableRegionSamplingHelper!!.isStopped).isTrue()
+ }
+
+ private inner class FakeBubbleTaskViewFactory : BubbleTaskViewFactory {
+ override fun create(): BubbleTaskView {
+ val taskViewTaskController = mock<TaskViewTaskController>()
+ val taskView = TaskView(context, taskViewTaskController)
+ val taskInfo = mock<ActivityManager.RunningTaskInfo>()
+ whenever(taskViewTaskController.taskInfo).thenReturn(taskInfo)
+ return BubbleTaskView(taskView, mainExecutor)
+ }
+ }
+
+ private inner class TestRegionSamplingProvider : RegionSamplingProvider {
+
+ lateinit var helper: TestableRegionSamplingHelper
+
+ override fun createHelper(
+ sampledView: View?,
+ callback: RegionSamplingHelper.SamplingCallback?,
+ backgroundExecutor: Executor?,
+ mainExecutor: Executor?
+ ): RegionSamplingHelper {
+ helper = TestableRegionSamplingHelper(sampledView, callback, backgroundExecutor,
+ mainExecutor)
+ return helper
+ }
+ }
+
+ private inner class TestableRegionSamplingHelper(
+ sampledView: View?,
+ samplingCallback: SamplingCallback?,
+ backgroundExecutor: Executor?,
+ mainExecutor: Executor?
+ ) : RegionSamplingHelper(sampledView, samplingCallback, backgroundExecutor, mainExecutor) {
+
+ var isStarted = false
+ var isStopped = false
+ var isDestroyed = false
+ var setWindowVisible = false
+ var setWindowInvisible = false
+
+ override fun start(initialSamplingBounds: Rect) {
+ super.start(initialSamplingBounds)
+ isStarted = true
+ }
+
+ override fun stop() {
+ super.stop()
+ isStopped = true
+ }
+
+ override fun stopAndDestroy() {
+ super.stopAndDestroy()
+ isDestroyed = true
+ }
+
+ override fun setWindowVisible(visible: Boolean) {
+ super.setWindowVisible(visible)
+ if (visible) {
+ setWindowVisible = true
+ } else {
+ setWindowInvisible = true
+ }
+ }
+
+ fun reset() {
+ isStarted = false
+ isStopped = false
+ isDestroyed = false
+ setWindowVisible = false
+ setWindowInvisible = false
+ }
+ }
+
+ private fun createExpandedViewManager(): BubbleExpandedViewManager {
+ return object : BubbleExpandedViewManager {
+ override val overflowBubbles: List<Bubble>
+ get() = Collections.emptyList()
+
+ override fun setOverflowListener(listener: BubbleData.Listener) {
+ }
+
+ override fun collapseStack() {
+ }
+
+ override fun updateWindowFlagsForBackpress(intercept: Boolean) {
+ }
+
+ override fun promoteBubbleFromOverflow(bubble: Bubble) {
+ }
+
+ override fun removeBubble(key: String, reason: Int) {
+ }
+
+ override fun dismissBubble(bubble: Bubble, reason: Int) {
+ }
+
+ override fun setAppBubbleTaskId(key: String, taskId: Int) {
+ }
+
+ override fun isStackExpanded(): Boolean {
+ return true
+ }
+
+ override fun isShowingAsBubbleBar(): Boolean {
+ return true
+ }
+
+ override fun hideCurrentInputMethod() {
+ }
+
+ override fun updateBubbleBarLocation(location: BubbleBarLocation) {
+ }
+ }
+ }
+
+ private class TestExecutor : ShellExecutor {
+
+ private val runnables: MutableList<Runnable> = mutableListOf()
+
+ override fun execute(runnable: Runnable) {
+ runnables.add(runnable)
+ }
+
+ override fun executeDelayed(runnable: Runnable, delayMillis: Long) {
+ execute(runnable)
+ }
+
+ override fun removeCallbacks(runnable: Runnable?) {}
+
+ override fun hasCallback(runnable: Runnable?): Boolean = false
+ }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml
index d1b98a6..0ed5a72 100644
--- a/libs/WindowManager/Shell/res/values-af/strings.xml
+++ b/libs/WindowManager/Shell/res/values-af/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"vou <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> in"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>-instellings"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Maak borrel toe"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Moenie dat gesprek \'n borrel word nie"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Klets met borrels"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Nuwe gesprekke verskyn as swerwende ikone, of borrels Tik op borrel om dit oop te maak. Sleep om dit te skuif."</string>
diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml
index 8044719..c4d9158 100644
--- a/libs/WindowManager/Shell/res/values-am/strings.xml
+++ b/libs/WindowManager/Shell/res/values-am/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>ን ሰብስብ"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"የ<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ቅንብሮች"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"አረፋን አሰናብት"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"ውይይቶችን በአረፋ አታሳይ"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"አረፋዎችን በመጠቀም ይወያዩ"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"አዲስ ውይይቶች እንደ ተንሳፋፊ አዶዎች ወይም አረፋዎች ሆነው ይታያሉ። አረፋን ለመክፈት መታ ያድርጉ። ለመውሰድ ይጎትቱት።"</string>
diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml
index 21aa34e..ced9ee9 100644
--- a/libs/WindowManager/Shell/res/values-ar/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ar/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"تصغير <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"إعدادات <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"إغلاق فقاعة المحادثة"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"عدم عرض المحادثة كفقاعة محادثة"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"الدردشة باستخدام فقاعات المحادثات"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"تظهر المحادثات الجديدة كرموز عائمة أو كفقاعات. انقر لفتح فقاعة المحادثة، واسحبها لتحريكها."</string>
diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml
index c59f470..273d043 100644
--- a/libs/WindowManager/Shell/res/values-as/strings.xml
+++ b/libs/WindowManager/Shell/res/values-as/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> সংকোচন কৰক"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ছেটিং"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"বাবল অগ্ৰাহ্য কৰক"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"বাৰ্তালাপ বাবল নকৰিব"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Bubbles ব্যৱহাৰ কৰি চাট কৰক"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"নতুন বাৰ্তালাপ উপঙি থকা চিহ্নসমূহ অথবা bubbles হিচাপে প্ৰদর্শিত হয়। Bubbles খুলিবলৈ টিপক। এইটো স্থানান্তৰ কৰিবলৈ টানি নিয়ক।"</string>
diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml
index 841323e..81bb544 100644
--- a/libs/WindowManager/Shell/res/values-az/strings.xml
+++ b/libs/WindowManager/Shell/res/values-az/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"yığcamlaşdırın: <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ayarları"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Yumrucuğu ləğv edin"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Söhbəti yumrucuqda göstərmə"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Yumrucuqlardan istifadə edərək söhbət edin"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Yeni söhbətlər üzən nişanlar və ya yumrucuqlar kimi görünür. Yumrucuğu açmaq üçün toxunun. Hərəkət etdirmək üçün sürüşdürün."</string>
diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
index 86ab548..898b844 100644
--- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"skupite oblačić <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Podešavanja za <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Odbaci oblačić"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ne koristi oblačiće za konverzaciju"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Ćaskajte u oblačićima"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Nove konverzacije se prikazuju kao plutajuće ikone ili oblačići. Dodirnite da biste otvorili oblačić. Prevucite da biste ga premestili."</string>
diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml
index bcbc1ae..c340729 100644
--- a/libs/WindowManager/Shell/res/values-be/strings.xml
+++ b/libs/WindowManager/Shell/res/values-be/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>: згарнуць"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Налады \"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>\""</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Адхіліць апавяшчэнне"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Не паказваць размову ў выглядзе ўсплывальных апавяшчэнняў"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Усплывальныя чаты"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Новыя размовы будуць паказвацца як рухомыя значкі ці ўсплывальныя чаты. Націсніце, каб адкрыць усплывальны чат. Перацягніце яго, каб перамясціць."</string>
diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml
index 4d1208b..076a815 100644
--- a/libs/WindowManager/Shell/res/values-bg/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bg/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"свиване на <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Настройки за <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Отхвърляне на балончетата"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Без балончета за разговора"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Чат с балончета"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Новите разговори се показват като плаващи икони, или балончета. Докоснете балонче, за да го отворите, или го плъзнете, за да го преместите."</string>
diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml
index bf8bc99..b0d6696 100644
--- a/libs/WindowManager/Shell/res/values-bn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bn/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> আড়াল করুন"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> সেটিংস"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"বাবল খারিজ করুন"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"কথোপকথন বাবল হিসেবে দেখাবে না"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"বাবল ব্যবহার করে চ্যাট করুন"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"নতুন কথোপকথন ভেসে থাকা আইকন বা বাবল হিসেবে দেখানো হয়। বাবল খুলতে ট্যাপ করুন। সেটি সরাতে ধরে টেনে আনুন।"</string>
diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml
index cf53d25..0196e5e 100644
--- a/libs/WindowManager/Shell/res/values-bs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bs/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"sužavanje oblačića <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Postavke aplikacije <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Odbaci oblačić"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Nemoj prikazivati razgovor u oblačićima"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatajte koristeći oblačiće"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Novi razgovori se prikazuju kao plutajuće ikone ili oblačići. Dodirnite da otvorite oblačić. Prevucite da ga premjestite."</string>
diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml
index 87ea62e..fa4b627 100644
--- a/libs/WindowManager/Shell/res/values-ca/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ca/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"replega <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Configuració de l\'aplicació <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Ignora la bombolla"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"No mostris la conversa com a bombolla"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Xateja amb bombolles"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Les converses noves es mostren com a icones flotants o bombolles. Toca per obrir una bombolla. Arrossega-la per moure-la."</string>
diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml
index e21213b..3956fca 100644
--- a/libs/WindowManager/Shell/res/values-cs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-cs/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"sbalit <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Nastavení <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Zavřít bublinu"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Nezobrazovat konverzaci v bublinách"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatujte pomocí bublin"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Nové konverzace se zobrazují jako plovoucí ikony, neboli bubliny. Klepnutím bublinu otevřete. Přetažením ji posunete."</string>
diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml
index 1c4647f..afe4a1ab 100644
--- a/libs/WindowManager/Shell/res/values-da/strings.xml
+++ b/libs/WindowManager/Shell/res/values-da/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"skjul <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Indstillinger for <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Afvis boble"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Vis ikke samtaler i bobler"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat ved hjælp af bobler"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Nye samtaler vises som svævende ikoner eller bobler. Tryk for at åbne boblen. Træk for at flytte den."</string>
diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml
index 88a5789..1e50339 100644
--- a/libs/WindowManager/Shell/res/values-de/strings.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> minimieren"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Einstellungen für <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Bubble schließen"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Unterhaltung nicht als Bubble anzeigen"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Bubbles zum Chatten verwenden"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Neue Unterhaltungen erscheinen als unverankerte Symbole, „Bubbles“ genannt. Wenn du eine Bubble öffnen möchtest, tippe sie an. Wenn du sie verschieben möchtest, zieh an ihr."</string>
diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml
index beeefee..5c3c6de 100644
--- a/libs/WindowManager/Shell/res/values-el/strings.xml
+++ b/libs/WindowManager/Shell/res/values-el/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"σύμπτυξη <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Ρυθμίσεις <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Παράβλ. για συννεφ."</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Να μην γίνει προβολή της συζήτησης σε συννεφάκια."</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Συζητήστε χρησιμοποιώντας συννεφάκια."</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Οι νέες συζητήσεις εμφανίζονται ως κινούμενα εικονίδια ή συννεφάκια. Πατήστε για να ανοίξετε το συννεφάκι. Σύρετε για να το μετακινήσετε."</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
index 72f4070..51c69e5 100644
--- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"collapse <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> settings"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Dismiss bubble"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Don’t bubble conversation"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat using bubbles"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"New conversations appear as floating icons, or bubbles. Tap to open bubble. Drag to move it."</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
index d11f521..f5b0a27 100644
--- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
@@ -73,6 +73,7 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"collapse <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> settings"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Dismiss bubble"</string>
+ <string name="bubble_fullscreen_text" msgid="1006758103218086231">"Move to fullscreen"</string>
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Don’t bubble conversation"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat using bubbles"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"New conversations appear as floating icons, or bubbles. Tap to open bubble. Drag to move it."</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
index 72f4070..51c69e5 100644
--- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"collapse <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> settings"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Dismiss bubble"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Don’t bubble conversation"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat using bubbles"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"New conversations appear as floating icons, or bubbles. Tap to open bubble. Drag to move it."</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
index 72f4070..51c69e5 100644
--- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"collapse <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> settings"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Dismiss bubble"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Don’t bubble conversation"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat using bubbles"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"New conversations appear as floating icons, or bubbles. Tap to open bubble. Drag to move it."</string>
diff --git a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
index 8002468..6292be5 100644
--- a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
@@ -73,6 +73,7 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"collapse <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> settings"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Dismiss bubble"</string>
+ <string name="bubble_fullscreen_text" msgid="1006758103218086231">"Move to fullscreen"</string>
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Don’t bubble conversation"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat using bubbles"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"New conversations appear as floating icons, or bubbles. Tap to open bubble. Drag to move it."</string>
diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
index 5756aae..8644780 100644
--- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"contraer <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Configuración de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Descartar burbuja"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"No mostrar la conversación en burbuja"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat con burbujas"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Las conversaciones nuevas aparecen como elementos flotantes o burbujas. Presiona para abrir la burbuja. Arrástrala para moverla."</string>
diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml
index 3c55bf6..9718bf1 100644
--- a/libs/WindowManager/Shell/res/values-es/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"contraer <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Ajustes de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Cerrar burbuja"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"No mostrar conversación en burbuja"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatea con burbujas"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Las conversaciones nuevas aparecen como iconos flotantes llamados \"burbujas\". Toca una burbuja para abrirla. Arrástrala para moverla."</string>
diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml
index d921967..d36a8d1 100644
--- a/libs/WindowManager/Shell/res/values-et/strings.xml
+++ b/libs/WindowManager/Shell/res/values-et/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"ahenda <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Rakenduse <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> seaded"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Sule mull"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ära kuva vestlust mullina"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Vestelge mullide abil"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Uued vestlused kuvatakse hõljuvate ikoonidena ehk mullidena. Puudutage mulli avamiseks. Lohistage mulli, et seda liigutada."</string>
diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml
index f319af1..2ee086e 100644
--- a/libs/WindowManager/Shell/res/values-eu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-eu/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"tolestu <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> aplikazioaren ezarpenak"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Baztertu burbuila"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ez erakutsi elkarrizketak burbuila gisa"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Txateatu burbuilen bidez"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Elkarrizketa berriak ikono gainerakor edo burbuila gisa agertzen dira. Sakatu burbuila irekitzeko. Arrasta ezazu mugitzeko."</string>
@@ -80,7 +82,7 @@
<string name="bubbles_user_education_manage" msgid="3460756219946517198">"Aplikazioaren burbuilak desaktibatzeko, sakatu Kudeatu"</string>
<string name="bubbles_user_education_got_it" msgid="3382046149225428296">"Ados"</string>
<string name="bubble_overflow_empty_title" msgid="2397251267073294968">"Ez dago azkenaldiko burbuilarik"</string>
- <string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Azken burbuilak eta baztertutakoak agertuko dira hemen"</string>
+ <string name="bubble_overflow_empty_subtitle" msgid="2627417924958633713">"Azkenaldiko burbuilak eta baztertutakoak agertuko dira hemen"</string>
<string name="bubble_bar_education_stack_title" msgid="2486903590422497245">"Txateatu burbuilak erabilita"</string>
<string name="bubble_bar_education_stack_text" msgid="2446934610817409820">"Elkarrizketa berriak ikono gisa agertzen dira pantailaren beheko izkinan. Zabaltzeko, saka itzazu. Baztertzeko, aldiz, arrasta itzazu."</string>
<string name="bubble_bar_education_manage_title" msgid="6148404487810835924">"Kontrolatu burbuilak edonoiz"</string>
diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml
index 44a0929..f4cdd5f 100644
--- a/libs/WindowManager/Shell/res/values-fa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fa/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"جمع کردن <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"تنظیمات <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"رد کردن حبابک"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"مکالمه در حباب نشان داده نشود"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"گپ بااستفاده از حبابکها"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"مکالمههای جدید بهصورت نمادهای شناور یا حبابکها نشان داده میشوند. برای باز کردن حبابکها تکضرب بزنید. برای جابهجایی، آن را بکشید."</string>
diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml
index 59cd6e0..6be2ee2 100644
--- a/libs/WindowManager/Shell/res/values-fi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fi/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"tiivistä <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>: asetukset"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Ohita kupla"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Älä näytä kuplia keskusteluista"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chattaile kuplien avulla"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Uudet keskustelut näkyvät kelluvina kuvakkeina tai kuplina. Avaa kupla napauttamalla. Siirrä sitä vetämällä."</string>
diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
index 02f832b..5470099 100644
--- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"réduire <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Paramètres <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Ignorer la bulle"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ne pas afficher les conversations dans des bulles"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Clavarder en utilisant des bulles"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Les nouvelles conversations s\'affichent sous forme d\'icônes flottantes (de bulles). Touchez une bulle pour l\'ouvrir. Faites-la glisser pour la déplacer."</string>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml
index 5d916f4..63b5994 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"Réduire <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Paramètres <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Fermer la bulle"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ne pas afficher la conversation dans une bulle"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatter en utilisant des bulles"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Les nouvelles conversations s\'affichent sous forme d\'icônes flottantes ou de bulles. Appuyez sur la bulle pour l\'ouvrir. Faites-la glisser pour la déplacer."</string>
diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml
index e1b2a7e..36ad521 100644
--- a/libs/WindowManager/Shell/res/values-gl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gl/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"contraer <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Configuración de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Ignorar burbulla"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Non mostrar a conversa como burbulla"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatear usando burbullas"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"As conversas novas aparecen como iconas flotantes ou burbullas. Toca para abrir a burbulla e arrastra para movela."</string>
diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml
index fecce73..868ef5b 100644
--- a/libs/WindowManager/Shell/res/values-gu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gu/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> નાનું કરો"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> સેટિંગ"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"બબલને છોડી દો"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"વાતચીતને બબલ કરશો નહીં"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"બબલનો ઉપયોગ કરીને ચૅટ કરો"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"નવી વાતચીત ફ્લોટિંગ આઇકન અથવા બબલ જેવી દેખાશે. બબલને ખોલવા માટે ટૅપ કરો. તેને ખસેડવા માટે ખેંચો."</string>
diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml
index f889f20..31c7307 100644
--- a/libs/WindowManager/Shell/res/values-hi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hi/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> को छोटा करें"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> की सेटिंग"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"बबल खारिज करें"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"बातचीत को बबल न करें"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"बबल्स का इस्तेमाल करके चैट करें"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"नई बातचीत फ़्लोटिंग आइकॉन या बबल्स की तरह दिखेंगी. बबल को खोलने के लिए टैप करें. इसे एक जगह से दूसरी जगह ले जाने के लिए खींचें और छोड़ें."</string>
diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml
index 04053c8..d99a65d8 100644
--- a/libs/WindowManager/Shell/res/values-hr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hr/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"sažmite oblačić <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Postavke za <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Odbaci oblačić"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Zaustavi razgovor u oblačićima"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Oblačići u chatu"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Novi razgovori pojavljuju se kao pomične ikone ili oblačići. Dodirnite za otvaranje oblačića. Povucite da biste ga premjestili."</string>
diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml
index bb52649..bed760e 100644
--- a/libs/WindowManager/Shell/res/values-hu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hu/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> összecsukása"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> beállításai"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Buborék elvetése"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ne jelenjen meg a beszélgetés buborékban"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Buborékokat használó csevegés"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Az új beszélgetések lebegő ikonként, vagyis buborékként jelennek meg. A buborék megnyitásához koppintson rá. Áthelyezéshez húzza a kívánt helyre."</string>
diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml
index fff5a10..fcb7254 100644
--- a/libs/WindowManager/Shell/res/values-hy/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hy/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>. ծալել"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> – կարգավորումներ"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Փակել ամպիկը"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Զրույցը չցուցադրել ամպիկի տեսքով"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Զրույցի ամպիկներ"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Նոր զրույցները կհայտնվեն լողացող պատկերակների կամ ամպիկների տեսքով։ Հպեք՝ ամպիկը բացելու համար։ Քաշեք՝ այն տեղափոխելու համար։"</string>
diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml
index a957754..85a9bbf 100644
--- a/libs/WindowManager/Shell/res/values-in/strings.xml
+++ b/libs/WindowManager/Shell/res/values-in/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"ciutkan <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Setelan <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Tutup balon"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Jangan gunakan percakapan balon"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat dalam tampilan balon"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Percakapan baru muncul sebagai ikon mengambang, atau balon. Ketuk untuk membuka balon. Tarik untuk memindahkannya."</string>
diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml
index 7b91768..8041162 100644
--- a/libs/WindowManager/Shell/res/values-is/strings.xml
+++ b/libs/WindowManager/Shell/res/values-is/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"minnka <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Stillingar <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Loka blöðru"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ekki setja samtal í blöðru"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Spjalla með blöðrum"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Ný samtöl birtast sem fljótandi tákn eða blöðrur. Ýttu til að opna blöðru. Dragðu hana til að færa."</string>
diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml
index 4ae4b36..3ba6873 100644
--- a/libs/WindowManager/Shell/res/values-it/strings.xml
+++ b/libs/WindowManager/Shell/res/values-it/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"comprimi <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Impostazioni <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Ignora bolla"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Non mettere la conversazione nella bolla"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatta utilizzando le bolle"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Le nuove conversazioni vengono mostrate come icone mobili o bolle. Tocca per aprire la bolla. Trascinala per spostarla."</string>
diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml
index ea73653..e1854fa1 100644
--- a/libs/WindowManager/Shell/res/values-iw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-iw/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"כיווץ של <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"הגדרות <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"סגירת בועה"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"אין להציג בועות לשיחה"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"לדבר בבועות"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"שיחות חדשות מופיעות כסמלים צפים, או בועות. יש להקיש כדי לפתוח בועה. יש לגרור כדי להזיז אותה."</string>
diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml
index 0cb921c..1f1ddc7 100644
--- a/libs/WindowManager/Shell/res/values-ja/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ja/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>を閉じます"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> の設定"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"バブルを閉じる"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"会話をバブルで表示しない"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"チャットでバブルを使う"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"新しい会話はフローティング アイコン(バブル)として表示されます。タップするとバブルが開きます。ドラッグしてバブルを移動できます。"</string>
diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml
index 16e99ba..e201a20 100644
--- a/libs/WindowManager/Shell/res/values-ka/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ka/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>-ის ჩაკეცვა"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>-ის პარამეტრები"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"ბუშტის დახურვა"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"აიკრძალოს საუბრის ბუშტები"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"ჩეთი ბუშტების გამოყენებით"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"ახალი საუბრები გამოჩნდება როგორც მოტივტივე ხატულები ან ბუშტები. შეეხეთ ბუშტის გასახსნელად. გადაიტანეთ ჩავლებით."</string>
diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml
index c6f558f..1c335dd 100644
--- a/libs/WindowManager/Shell/res/values-kk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kk/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>: жию"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> параметрлері"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Қалқымалы хабарды жабу"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Әңгіменің қалқыма хабары көрсетілмесін"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Қалқыма хабарлар арқылы сөйлесу"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Жаңа әңгімелер қалқыма белгішелер немесе хабарлар түрінде көрсетіледі. Қалқыма хабарды ашу үшін түртіңіз. Жылжыту үшін сүйреңіз."</string>
diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml
index 508ea48..d0cceee 100644
--- a/libs/WindowManager/Shell/res/values-km/strings.xml
+++ b/libs/WindowManager/Shell/res/values-km/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"បង្រួម <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"ការកំណត់ <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"ច្រានចោលពពុះ"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"កុំបង្ហាញការសន្ទនាជាពពុះ"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"ជជែកដោយប្រើពពុះ"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"ការសន្ទនាថ្មីៗបង្ហាញជាពពុះ ឬរូបអណ្ដែត។ ចុច ដើម្បីបើកពពុះ។ អូស ដើម្បីផ្លាស់ទីពពុះនេះ។"</string>
diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml
index 1fc627b..63b5c68 100644
--- a/libs/WindowManager/Shell/res/values-kn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kn/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> ಅನ್ನು ಕುಗ್ಗಿಸಿ"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"ಬಬಲ್ ವಜಾಗೊಳಿಸಿ"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"ಸಂಭಾಷಣೆಯನ್ನು ಬಬಲ್ ಮಾಡಬೇಡಿ"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"ಬಬಲ್ಸ್ ಬಳಸಿ ಚಾಟ್ ಮಾಡಿ"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"ಹೊಸ ಸಂಭಾಷಣೆಗಳು ತೇಲುವ ಐಕಾನ್ಗಳು ಅಥವಾ ಬಬಲ್ಸ್ ಆಗಿ ಗೋಚರಿಸುತ್ತವೆ. ಬಬಲ್ ತೆರೆಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ. ಅದನ್ನು ಡ್ರ್ಯಾಗ್ ಮಾಡಲು ಎಳೆಯಿರಿ."</string>
diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml
index 96d360e..b5efd10 100644
--- a/libs/WindowManager/Shell/res/values-ko/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ko/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> 접기"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> 설정"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"대화창 닫기"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"대화를 대화창으로 표시하지 않기"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"대화창으로 채팅하기"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"새로운 대화가 플로팅 아이콘인 대화창으로 표시됩니다. 대화창을 열려면 탭하세요. 드래그하여 이동할 수 있습니다."</string>
diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml
index 662c2eae..e001efe 100644
--- a/libs/WindowManager/Shell/res/values-ky/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ky/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> жыйыштыруу"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> параметрлери"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Калкып чыкма билдирмени жабуу"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Жазышууда калкып чыкма билдирмелер көрүнбөсүн"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Калкып чыкма билдирмелер аркылуу маектешүү"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Жаңы жазышуулар калкыма сүрөтчөлөр же калкып чыкма билдирмелер түрүндө көрүнөт. Калкып чыкма билдирмелерди ачуу үчүн тийип коюңуз. Жылдыруу үчүн сүйрөңүз."</string>
diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml
index ed6b378..029c95b 100644
--- a/libs/WindowManager/Shell/res/values-lo/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lo/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"ຫຍໍ້ <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> ລົງ"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"ການຕັ້ງຄ່າ <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"ປິດຟອງໄວ້"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"ຢ່າໃຊ້ຟອງໃນການສົນທະນາ"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"ສົນທະນາໂດຍໃຊ້ຟອງ"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"ການສົນທະນາໃໝ່ຈະປາກົດເປັນໄອຄອນ ຫຼື ຟອງແບບລອຍ. ແຕະເພື່ອເປີດຟອງ. ລາກເພື່ອຍ້າຍມັນ."</string>
diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml
index f71d650..791ddcd 100644
--- a/libs/WindowManager/Shell/res/values-lt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lt/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"sutraukti „<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>“"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"„<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>“ nustatymai"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Atsisakyti burbulo"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Nerodyti pokalbio burbule"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Pokalbis naudojant burbulus"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Nauji pokalbiai rodomi kaip slankiosios piktogramos arba burbulai. Palieskite, kad atidarytumėte burbulą. Vilkite, kad perkeltumėte."</string>
diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml
index abadef7..8a86687 100644
--- a/libs/WindowManager/Shell/res/values-lv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lv/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"Sakļaut “<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>”"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Lietotnes <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> iestatījumi"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Nerādīt burbuli"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Nerādīt sarunu burbuļos"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Tērzēšana, izmantojot burbuļus"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Jaunas sarunas tiek rādītas kā peldošas ikonas vai burbuļi. Pieskarieties, lai atvērtu burbuli. Velciet, lai to pārvietotu."</string>
diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml
index 0576fc0..3a6b2f0 100644
--- a/libs/WindowManager/Shell/res/values-mk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mk/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"собери <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Поставки за <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Отфрли балонче"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Не прикажувај го разговорот во балончиња"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Разговор во балончиња"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Новите разговори ќе се појавуваат како лебдечки икони или балончиња. Допрете за отворање на балончето. Повлечете за да го преместите."</string>
diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml
index 6e7ea08..26e4a46 100644
--- a/libs/WindowManager/Shell/res/values-ml/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ml/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> ചുരുക്കുക"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ക്രമീകരണം"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"ബബിൾ ഡിസ്മിസ് ചെയ്യൂ"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"സംഭാഷണം ബബിൾ ചെയ്യരുത്"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"ബബിളുകൾ ഉപയോഗിച്ച് ചാറ്റ് ചെയ്യുക"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"പുതിയ സംഭാഷണങ്ങൾ ഫ്ലോട്ടിംഗ് ഐക്കണുകളോ ബബിളുകളോ ആയി ദൃശ്യമാവുന്നു. ബബിൾ തുറക്കാൻ ടാപ്പ് ചെയ്യൂ. ഇത് നീക്കാൻ വലിച്ചിടുക."</string>
diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml
index d69ec05..505a4ad 100644
--- a/libs/WindowManager/Shell/res/values-mn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mn/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>-г хураах"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>-н тохиргоо"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Бөмбөлгийг хаах"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Харилцан яриаг бүү бөмбөлөг болго"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Бөмбөлөг ашиглан чатлаарай"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Шинэ харилцан яриа нь хөвөгч дүрс тэмдэг эсвэл бөмбөлөг хэлбэрээр харагддаг. Бөмбөлгийг нээхийн тулд товшино уу. Түүнийг зөөхийн тулд чирнэ үү."</string>
diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml
index 33ba1c2..cc35f11 100644
--- a/libs/WindowManager/Shell/res/values-mr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mr/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> कोलॅप्स करा"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> सेटिंग्ज"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"बबल डिसमिस करा"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"संभाषणाला बबल करू नका"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"बबल वापरून चॅट करा"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"नवीन संभाषणे फ्लोटिंग आयकन किंवा बबल म्हणून दिसतात. बबल उघडण्यासाठी टॅप करा. हे हलवण्यासाठी ड्रॅग करा."</string>
diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml
index e024e4b..61d6614 100644
--- a/libs/WindowManager/Shell/res/values-ms/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ms/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"kuncupkan <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Tetapan <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Ketepikan gelembung"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Jangan jadikan perbualan dalam bentuk gelembung"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Bersembang menggunakan gelembung"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Perbualan baharu muncul sebagai ikon terapung atau gelembung. Ketik untuk membuka gelembung. Seret untuk mengalihkan gelembung tersebut."</string>
diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml
index bd680b4..7841e07 100644
--- a/libs/WindowManager/Shell/res/values-my/strings.xml
+++ b/libs/WindowManager/Shell/res/values-my/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> ကို ချုံ့ရန်"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ဆက်တင်များ"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"ပူဖောင်းကွက် ပယ်ရန်"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"စကားဝိုင်းကို ပူဖောင်းကွက် မပြုလုပ်ပါနှင့်"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"ပူဖောင်းကွက် သုံး၍ ချတ်လုပ်ခြင်း"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"စကားဝိုင်းအသစ်များကို မျောနေသည့် သင်္ကေတများ သို့မဟုတ် ပူဖောင်းကွက်များအဖြစ် မြင်ရပါမည်။ ပူဖောင်းကွက်ကိုဖွင့်ရန် တို့ပါ။ ရွှေ့ရန် ၎င်းကို ဖိဆွဲပါ။"</string>
diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml
index 896d9fd..ea2ae1b 100644
--- a/libs/WindowManager/Shell/res/values-nb/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nb/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"skjul <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>-innstillinger"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Lukk boblen"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ikke vis samtaler i bobler"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat med bobler"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Nye samtaler vises som flytende ikoner eller bobler. Trykk for å åpne en boble. Dra for å flytte den."</string>
diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml
index 113085e..a3bd5ee 100644
--- a/libs/WindowManager/Shell/res/values-ne/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ne/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> कोल्याप्स गर्नुहोस्"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> का सेटिङहरू"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"बबल खारेज गर्नुहोस्"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"वार्तालाप बबलको रूपमा नदेखाउनुहोस्"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"बबलहरू प्रयोग गरी कुराकानी गर्नुहोस्"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"नयाँ वार्तालापहरू तैरने आइकन वा बबलका रूपमा देखिन्छन्। बबल खोल्न ट्याप गर्नुहोस्। बबल सार्न सो बबललाई ड्र्याग गर्नुहोस्।"</string>
diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml
index a9c06fb..ad2c60f 100644
--- a/libs/WindowManager/Shell/res/values-nl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nl/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> samenvouwen"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Instellingen voor <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Bubbel sluiten"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Gesprekken niet in bubbels tonen"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatten met bubbels"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Nieuwe gesprekken worden als zwevende iconen of bubbels getoond. Tik om een bubbel te openen. Sleep om een bubbel te verplaatsen."</string>
diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml
index a80cfc2..76f2715 100644
--- a/libs/WindowManager/Shell/res/values-or/strings.xml
+++ b/libs/WindowManager/Shell/res/values-or/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> ସଙ୍କୁଚିତ କରନ୍ତୁ"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ସେଟିଂସ୍"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"ବବଲ୍ ଖାରଜ କରନ୍ତୁ"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"ବାର୍ତ୍ତାଳାପକୁ ବବଲ୍ କରନ୍ତୁ ନାହିଁ"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"ବବଲଗୁଡ଼ିକୁ ବ୍ୟବହାର କରି ଚାଟ୍ କରନ୍ତୁ"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"ନୂଆ ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ ଫ୍ଲୋଟିଂ ଆଇକନ୍ କିମ୍ବା ବବଲ୍ ଭାବେ ଦେଖାଯିବ। ବବଲ୍ ଖୋଲିବାକୁ ଟାପ୍ କରନ୍ତୁ। ଏହାକୁ ମୁଭ୍ କରିବାକୁ ଟାଣନ୍ତୁ।"</string>
diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml
index 7257161..cd7fd47 100644
--- a/libs/WindowManager/Shell/res/values-pa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pa/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> ਨੂੰ ਸਮੇਟੋ"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ਸੈਟਿੰਗਾਂ"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"ਬਬਲ ਨੂੰ ਖਾਰਜ ਕਰੋ"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"ਗੱਲਬਾਤ \'ਤੇ ਬਬਲ ਨਾ ਲਾਓ"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"ਬਬਲ ਵਰਤਦੇ ਹੋਏ ਚੈਟ ਕਰੋ"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"ਨਵੀਆਂ ਗੱਲਾਂਬਾਤਾਂ ਫਲੋਟਿੰਗ ਪ੍ਰਤੀਕਾਂ ਜਾਂ ਬਬਲ ਦੇ ਰੂਪ ਵਿੱਚ ਦਿਸਦੀਆਂ ਹਨ। ਬਬਲ ਨੂੰ ਖੋਲ੍ਹਣ ਲਈ ਟੈਪ ਕਰੋ। ਇਸਨੂੰ ਲਿਜਾਣ ਲਈ ਘਸੀਟੋ।"</string>
diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml
index 7600db0..d33b6f1 100644
--- a/libs/WindowManager/Shell/res/values-pl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pl/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"zwiń dymek <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> – ustawienia"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Zamknij dymek"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Nie wyświetlaj rozmowy jako dymka"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Czatuj, korzystając z dymków"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Nowe rozmowy będą wyświetlane jako pływające ikony lub dymki. Kliknij, by otworzyć dymek. Przeciągnij, by go przenieść."</string>
diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
index 58c78f3..c7a00ff 100644
--- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"fechar <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Configurações de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Dispensar balão"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Não criar balões de conversa"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Converse usando balões"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Novas conversas aparecerão como ícones flutuantes, ou balões. Toque para abrir o balão. Arraste para movê-lo."</string>
diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
index f433413..d141447 100644
--- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"reduzir <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Definições de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Ignorar balão"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Não apresentar a conversa em balões"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Converse no chat através de balões"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"As novas conversas aparecem como ícones flutuantes ou balões. Toque para abrir o balão. Arraste para o mover."</string>
diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml
index 58c78f3..c7a00ff 100644
--- a/libs/WindowManager/Shell/res/values-pt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"fechar <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Configurações de <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Dispensar balão"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Não criar balões de conversa"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Converse usando balões"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Novas conversas aparecerão como ícones flutuantes, ou balões. Toque para abrir o balão. Arraste para movê-lo."</string>
diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml
index 077503a..9bc7660 100644
--- a/libs/WindowManager/Shell/res/values-ro/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ro/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"restrânge <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Setări <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Închide balonul"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Nu afișa conversația în balon"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chat cu baloane"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Conversațiile noi apar ca pictograme flotante sau baloane. Atinge pentru a deschide balonul. Trage pentru a-l muta."</string>
diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml
index 5471027..044e3b02 100644
--- a/libs/WindowManager/Shell/res/values-ru/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ru/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"Свернуть <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>: настройки"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Скрыть всплывающий чат"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Не показывать всплывающий чат для разговора"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Всплывающие чаты"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Новые разговоры будут появляться в виде плавающих значков, или всплывающих чатов. Чтобы открыть чат, нажмите на него, а чтобы переместить – перетащите."</string>
diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml
index 3f015f6..da2541e 100644
--- a/libs/WindowManager/Shell/res/values-si/strings.xml
+++ b/libs/WindowManager/Shell/res/values-si/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> හකුළන්න"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> සැකසීම්"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"බුබුලු ඉවත ලන්න"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"සංවාදය බුබුලු නොදමන්න"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"බුබුලු භාවිතයෙන් කතාබහ කරන්න"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"නව සංවාද පාවෙන අයිකන හෝ බුබුලු ලෙස දිස් වේ. බුබුල විවෘත කිරීමට තට්ටු කරන්න. එය ගෙන යාමට අදින්න."</string>
diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml
index fa376e7..394a4ca 100644
--- a/libs/WindowManager/Shell/res/values-sk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sk/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"zbaliť <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Nastavenia aplikácie <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Zavrieť bublinu"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Nezobrazovať konverzáciu ako bublinu"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Čet pomocou bublín"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Nové konverzácie sa zobrazujú ako plávajúce ikony či bubliny. Bublinu otvoríte klepnutím. Premiestnite ju presunutím."</string>
diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml
index 8538668..a90c2c2 100644
--- a/libs/WindowManager/Shell/res/values-sl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sl/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"strnitev oblačka <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Nastavitve za <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Opusti oblaček"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Pogovora ne prikaži v oblačku"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Klepet z oblački"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Novi pogovori so prikazani kot lebdeče ikone ali oblački. Če želite odpreti oblaček, se ga dotaknite. Če ga želite premakniti, ga povlecite."</string>
diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml
index f77a43d..706e75f 100644
--- a/libs/WindowManager/Shell/res/values-sq/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sq/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"palos <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Cilësimet e <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Hiqe flluskën"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Mos e vendos bisedën në flluskë"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Bisedo duke përdorur flluskat"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Bisedat e reja shfaqen si ikona pluskuese ose flluska. Trokit për të hapur flluskën. Zvarrit për ta zhvendosur."</string>
diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml
index af7686a..539a00a2 100644
--- a/libs/WindowManager/Shell/res/values-sr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sr/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"скупите облачић <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Подешавања за <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Одбаци облачић"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Не користи облачиће за конверзацију"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Ћаскајте у облачићима"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Нове конверзације се приказују као плутајуће иконе или облачићи. Додирните да бисте отворили облачић. Превуците да бисте га преместили."</string>
diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml
index 0d08d8d..549eb10 100644
--- a/libs/WindowManager/Shell/res/values-sv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sv/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"komprimera <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Inställningar för <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Stäng bubbla"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Visa inte konversationen i bubblor"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Chatta med bubblor"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Nya konversationer visas som flytande ikoner, så kallade bubblor. Tryck på bubblan om du vill öppna den. Dra den om du vill flytta den."</string>
diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml
index 448f6249..9c34690 100644
--- a/libs/WindowManager/Shell/res/values-sw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sw/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"kunja <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Mipangilio ya <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Ondoa kiputo"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Usiweke viputo kwenye mazungumzo"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Piga gumzo ukitumia viputo"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Mazungumzo mapya huonekena kama aikoni au viputo vinavyoelea. Gusa ili ufungue kiputo. Buruta ili ukisogeze."</string>
diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml
index 1268929..7e996f3 100644
--- a/libs/WindowManager/Shell/res/values-ta/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ta/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> ஐச் சுருக்கும்"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> அமைப்புகள்"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"குமிழை அகற்று"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"உரையாடலைக் குமிழாக்காதே"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"குமிழ்களைப் பயன்படுத்தி அரட்டையடியுங்கள்"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"புதிய உரையாடல்கள் மிதக்கும் ஐகான்களாகவோ குமிழ்களாகவோ தோன்றும். குமிழைத் திறக்க தட்டவும். நகர்த்த இழுக்கவும்."</string>
diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml
index 524e558..984cea8 100644
--- a/libs/WindowManager/Shell/res/values-te/strings.xml
+++ b/libs/WindowManager/Shell/res/values-te/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>ను కుదించండి"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> సెట్టింగ్లు"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"బబుల్ను విస్మరించు"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"సంభాషణను బబుల్ చేయవద్దు"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"బబుల్స్ను ఉపయోగించి చాట్ చేయండి"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"కొత్త సంభాషణలు తేలియాడే చిహ్నాలుగా లేదా బబుల్స్ లాగా కనిపిస్తాయి. బబుల్ని తెరవడానికి నొక్కండి. తరలించడానికి లాగండి."</string>
diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml
index 00a395f..3460b07 100644
--- a/libs/WindowManager/Shell/res/values-th/strings.xml
+++ b/libs/WindowManager/Shell/res/values-th/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"ยุบ <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"การตั้งค่า <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"ปิดบับเบิล"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"ไม่ต้องแสดงการสนทนาเป็นบับเบิล"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"แชทโดยใช้บับเบิล"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"การสนทนาใหม่ๆ จะปรากฏเป็นไอคอนแบบลอยหรือบับเบิล แตะเพื่อเปิดบับเบิล ลากเพื่อย้ายที่"</string>
diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml
index 50a9211..dc30912 100644
--- a/libs/WindowManager/Shell/res/values-tl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tl/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"i-collapse ang <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Mga setting ng <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"I-dismiss ang bubble"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Huwag ipakita sa bubble ang mga pag-uusap"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Mag-chat gamit ang bubbles"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Lumalabas bilang mga nakalutang na icon o bubble ang mga bagong pag-uusap. I-tap para buksan ang bubble. I-drag para ilipat ito."</string>
diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml
index ddd4206..e9e2173 100644
--- a/libs/WindowManager/Shell/res/values-tr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tr/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"daralt: <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ayarları"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Baloncuğu kapat"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Görüşmeyi baloncuk olarak görüntüleme"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Baloncukları kullanarak sohbet edin"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Yeni görüşmeler kayan simgeler veya baloncuk olarak görünür. Açmak için baloncuğa dokunun. Baloncuğu taşımak için sürükleyin."</string>
diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml
index 1dcdfe6..e1b6e35 100644
--- a/libs/WindowManager/Shell/res/values-uk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uk/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"згорнути \"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>\""</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Налаштування параметра \"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>\""</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Закрити підказку"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Не показувати спливаючі чати для розмов"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Спливаючий чат"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Нові повідомлення чату з\'являються у вигляді спливаючих значків. Щоб відкрити чат, натисніть його, а щоб перемістити – перетягніть."</string>
diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml
index 26ece5c..0508e6d 100644
--- a/libs/WindowManager/Shell/res/values-ur/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ur/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g> کو سکیڑیں"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> ترتیبات"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"بلبلہ برخاست کریں"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"گفتگو بلبلہ نہ کریں"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"بلبلے کے ذریعے چیٹ کریں"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"نئی گفتگوئیں فلوٹنگ آئیکن یا بلبلے کے طور پر ظاہر ہوں گی۔ بلبلہ کھولنے کے لیے تھپتھپائیں۔ اسے منتقل کرنے کے لیے گھسیٹیں۔"</string>
diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml
index 90b9a3f..5de3b7b 100644
--- a/libs/WindowManager/Shell/res/values-uz/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uz/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>ni yopish"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> sozlamalari"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Bulutchani yopish"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Suhbatlar bulutchalar shaklida chiqmasin"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Bulutchalar yordamida subhatlashish"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Yangi xabarlar qalqib chiquvchi belgilar yoki bulutchalar kabi chiqadi. Xabarni ochish uchun bildirishnoma ustiga bosing. Xabarni qayta joylash uchun bildirishnomani suring."</string>
diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml
index 90471f9..9b2f898 100644
--- a/libs/WindowManager/Shell/res/values-vi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-vi/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"thu gọn <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"Cài đặt <xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Đóng bong bóng"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Dừng sử dụng bong bóng cho cuộc trò chuyện"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Trò chuyện bằng bong bóng trò chuyện"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Các cuộc trò chuyện mới sẽ xuất hiện dưới dạng biểu tượng nổi hoặc bong bóng trò chuyện. Nhấn để mở bong bóng trò chuyện. Kéo để di chuyển bong bóng trò chuyện."</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
index 0aa52ac..b45b76e 100644
--- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"收起“<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>”"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>设置"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"关闭消息气泡"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"不以消息气泡形式显示对话"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"使用消息气泡聊天"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"新对话会以浮动图标或消息气泡形式显示。点按即可打开消息气泡。拖动即可移动消息气泡。"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
index 8a5be6a..ae776b8 100644
--- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"收埋<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"「<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>」設定"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"關閉小視窗氣泡"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"不要透過小視窗顯示對話"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"使用小視窗進行即時通訊"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"新對話會以浮動圖示 (小視窗) 顯示。輕按即可開啟小視窗。拖曳即可移動小視窗。"</string>
diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
index d1cc4bb..5bfc6b8 100644
--- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"收合「<xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>」"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"「<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>」設定"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"關閉對話框"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"不要以對話框形式顯示對話"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"透過對話框來聊天"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"新的對話會以浮動圖示或對話框形式顯示。輕觸即可開啟對話框,拖曳則可移動對話框。"</string>
diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml
index 6163a97..0598d62 100644
--- a/libs/WindowManager/Shell/res/values-zu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zu/strings.xml
@@ -73,6 +73,8 @@
<string name="bubble_accessibility_announce_collapse" msgid="3178806224494537097">"goqa <xliff:g id="BUBBLE_TITLE">%1$s</xliff:g>"</string>
<string name="bubbles_app_settings" msgid="3617224938701566416">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g> izilungiselelo"</string>
<string name="bubble_dismiss_text" msgid="8816558050659478158">"Cashisa ibhamuza"</string>
+ <!-- no translation found for bubble_fullscreen_text (1006758103218086231) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="310000317885712693">"Ungayibhamuzi ingxoxo"</string>
<string name="bubbles_user_education_title" msgid="2112319053732691899">"Xoxa usebenzisa amabhamuza"</string>
<string name="bubbles_user_education_description" msgid="4215862563054175407">"Izingxoxo ezintsha zivela njengezithonjana ezintantayo, noma amabhamuza. Thepha ukuze uvule ibhamuza. Hudula ukuze ulihambise."</string>
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/handles/RegionSamplingHelper.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/handles/RegionSamplingHelper.java
index b92b8ef..a06cf78 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/handles/RegionSamplingHelper.java
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/handles/RegionSamplingHelper.java
@@ -329,7 +329,7 @@
/**
* Get the sampled region of interest from the sampled view
* @param sampledView The view that this helper is attached to for convenience
- * @return the region to be sampled in sceen coordinates. Return {@code null} to avoid
+ * @return the region to be sampled in screen coordinates. Return {@code null} to avoid
* sampling in this frame
*/
Rect getSampledRegion(View sampledView);
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/pip/PipContentOverlay.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/pip/PipContentOverlay.java
index cf39415..6c83d88 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/pip/PipContentOverlay.java
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/pip/PipContentOverlay.java
@@ -29,7 +29,6 @@
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
import android.window.TaskSnapshot;
/**
@@ -75,7 +74,7 @@
public PipColorOverlay(Context context) {
mContext = context;
- mLeash = new SurfaceControl.Builder(new SurfaceSession())
+ mLeash = new SurfaceControl.Builder()
.setCallsite(TAG)
.setName(LAYER_NAME)
.setColorLayer()
@@ -123,7 +122,7 @@
public PipSnapshotOverlay(TaskSnapshot snapshot, Rect sourceRectHint) {
mSnapshot = snapshot;
mSourceRectHint = new Rect(sourceRectHint);
- mLeash = new SurfaceControl.Builder(new SurfaceSession())
+ mLeash = new SurfaceControl.Builder()
.setCallsite(TAG)
.setName(LAYER_NAME)
.build();
@@ -183,7 +182,7 @@
mBitmap = Bitmap.createBitmap(overlaySize, overlaySize, Bitmap.Config.ARGB_8888);
prepareAppIconOverlay(appIcon);
- mLeash = new SurfaceControl.Builder(new SurfaceSession())
+ mLeash = new SurfaceControl.Builder()
.setCallsite(TAG)
.setName(LAYER_NAME)
.build();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/AppToWebUtils.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/AppToWebUtils.kt
new file mode 100644
index 0000000..05ce361
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/AppToWebUtils.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.
+ */
+
+@file:JvmName("AppToWebUtils")
+
+package com.android.wm.shell.apptoweb
+
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.net.Uri
+
+private val browserIntent = Intent()
+ .setAction(Intent.ACTION_VIEW)
+ .addCategory(Intent.CATEGORY_BROWSABLE)
+ .setData(Uri.parse("http:"))
+
+/**
+ * Returns a boolean indicating whether a given package is a browser app.
+ */
+fun isBrowserApp(context: Context, packageName: String, userId: Int): Boolean {
+ browserIntent.setPackage(packageName)
+ val list = context.packageManager.queryIntentActivitiesAsUser(
+ browserIntent, PackageManager.MATCH_ALL, userId
+ )
+
+ list.forEach {
+ if (it.activityInfo != null && it.handleAllWebDataURI) {
+ return true
+ }
+ }
+ return false
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/AssistContentRequester.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/AssistContentRequester.kt
new file mode 100644
index 0000000..249185e
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/AssistContentRequester.kt
@@ -0,0 +1,126 @@
+/*
+ * 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.apptoweb
+
+import android.app.ActivityTaskManager
+import android.app.IActivityTaskManager
+import android.app.IAssistDataReceiver
+import android.app.assist.AssistContent
+import android.content.Context
+import android.graphics.Bitmap
+import android.os.Bundle
+import android.os.RemoteException
+import android.util.Slog
+import java.lang.ref.WeakReference
+import java.util.Collections
+import java.util.WeakHashMap
+import java.util.concurrent.Executor
+
+/**
+ * Can be used to request the AssistContent from a provided task id, useful for getting the web uri
+ * if provided from the task.
+ */
+class AssistContentRequester(
+ context: Context,
+ private val callBackExecutor: Executor,
+ private val systemInteractionExecutor: Executor
+) {
+ interface Callback {
+ // Called when the [AssistContent] of the requested task is available.
+ fun onAssistContentAvailable(assistContent: AssistContent?)
+ }
+
+ private val activityTaskManager: IActivityTaskManager = ActivityTaskManager.getService()
+ private val attributionTag: String? = context.attributionTag
+ private val packageName: String = context.applicationContext.packageName
+
+ // If system loses the callback, our internal cache of original callback will also get cleared.
+ private val pendingCallbacks = Collections.synchronizedMap(WeakHashMap<Any, Callback>())
+
+ /**
+ * Request the [AssistContent] from the task with the provided id.
+ *
+ * @param taskId to query for the content.
+ * @param callback to call when the content is available, called on the main thread.
+ */
+ fun requestAssistContent(taskId: Int, callback: Callback) {
+ // ActivityTaskManager interaction here is synchronous, so call off the main thread.
+ systemInteractionExecutor.execute {
+ try {
+ val success = activityTaskManager.requestAssistDataForTask(
+ AssistDataReceiver(callback, this),
+ taskId,
+ packageName,
+ attributionTag,
+ false /* fetchStructure */
+ )
+ if (!success) {
+ executeOnMainExecutor { callback.onAssistContentAvailable(null) }
+ }
+ } catch (e: RemoteException) {
+ Slog.e(TAG, "Requesting assist content failed for task: $taskId", e)
+ }
+ }
+ }
+
+ private fun executeOnMainExecutor(callback: Runnable) {
+ callBackExecutor.execute(callback)
+ }
+
+ private class AssistDataReceiver(
+ callback: Callback,
+ parent: AssistContentRequester
+ ) : IAssistDataReceiver.Stub() {
+ // The AssistDataReceiver binder callback object is passed to a system server, that may
+ // keep hold of it for longer than the lifetime of the AssistContentRequester object,
+ // potentially causing a memory leak. In the callback passed to the system server, only
+ // keep a weak reference to the parent object and lookup its callback if it still exists.
+ private val parentRef: WeakReference<AssistContentRequester>
+ private val callbackKey = Any()
+
+ init {
+ parent.pendingCallbacks[callbackKey] = callback
+ parentRef = WeakReference(parent)
+ }
+
+ override fun onHandleAssistData(data: Bundle?) {
+ val content = data?.getParcelable(ASSIST_KEY_CONTENT, AssistContent::class.java)
+ if (content == null) {
+ Slog.d(TAG, "Received AssistData, but no AssistContent found")
+ return
+ }
+ val requester = parentRef.get()
+ if (requester != null) {
+ val callback = requester.pendingCallbacks[callbackKey]
+ if (callback != null) {
+ requester.executeOnMainExecutor { callback.onAssistContentAvailable(content) }
+ } else {
+ Slog.d(TAG, "Callback received after calling UI was disposed of")
+ }
+ } else {
+ Slog.d(TAG, "Callback received after Requester was collected")
+ }
+ }
+
+ override fun onHandleAssistScreenshot(screenshot: Bitmap) {}
+ }
+
+ companion object {
+ private const val TAG = "AssistContentRequester"
+ private const val ASSIST_KEY_CONTENT = "content"
+ }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OWNERS
index bfe1306a..6207e5b0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apptoweb/OWNERS
@@ -1,6 +1,8 @@
atsjenk@google.com
jorgegil@google.com
madym@google.com
+mattsziklay@google.com
+mdehaini@google.com
pbdr@google.com
tkachenkoi@google.com
vaniadesmonda@google.com
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index ef679da..1563994 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -573,8 +573,14 @@
private void startBackNavigation(@NonNull BackTouchTracker touchTracker) {
try {
startLatencyTracking();
+ final BackAnimationAdapter adapter = mEnableAnimations.get()
+ ? mBackAnimationAdapter : null;
+ if (adapter != null && mShellBackAnimationRegistry.hasSupportedAnimatorsChanged()) {
+ adapter.updateSupportedAnimators(
+ mShellBackAnimationRegistry.getSupportedAnimators());
+ }
mBackNavigationInfo = mActivityTaskManager.startBackNavigation(
- mNavigationObserver, mEnableAnimations.get() ? mBackAnimationAdapter : null);
+ mNavigationObserver, adapter);
onBackNavigationInfoReceived(mBackNavigationInfo, touchTracker);
} catch (RemoteException remoteException) {
Log.e(TAG, "Failed to initAnimation", remoteException);
@@ -976,7 +982,6 @@
mShellBackAnimationRegistry.resetDefaultCrossActivity();
cancelLatencyTracking();
mReceivedNullNavigationInfo = false;
- mBackTransitionHandler.mLastTrigger = triggerBack;
if (mBackNavigationInfo != null) {
mPreviousNavigationType = mBackNavigationInfo.getType();
mBackNavigationInfo.onBackNavigationFinished(triggerBack);
@@ -1097,7 +1102,6 @@
endLatencyTracking();
if (!validateAnimationTargets(apps)) {
Log.e(TAG, "Invalid animation targets!");
- mBackTransitionHandler.consumeQueuedTransitionIfNeeded();
return;
}
mBackAnimationFinishedCallback = finishedCallback;
@@ -1107,7 +1111,6 @@
return;
}
kickStartAnimation();
- mBackTransitionHandler.consumeQueuedTransitionIfNeeded();
});
}
@@ -1115,7 +1118,6 @@
public void onAnimationCancelled() {
mShellExecutor.execute(
() -> {
- mBackTransitionHandler.consumeQueuedTransitionIfNeeded();
if (!mShellBackAnimationRegistry.cancel(
mBackNavigationInfo != null
? mBackNavigationInfo.getType()
@@ -1154,8 +1156,6 @@
boolean mCloseTransitionRequested;
SurfaceControl.Transaction mFinishOpenTransaction;
Transitions.TransitionFinishCallback mFinishOpenTransitionCallback;
- QueuedTransition mQueuedTransition = null;
- boolean mLastTrigger;
// The Transition to make behindActivity become visible
IBinder mPrepareOpenTransition;
// The Transition to make behindActivity become invisible, if prepare open exist and
@@ -1172,24 +1172,19 @@
}
}
- void consumeQueuedTransitionIfNeeded() {
- if (mQueuedTransition != null) {
- mQueuedTransition.consume();
- mQueuedTransition = null;
- }
- }
-
private void applyFinishOpenTransition() {
- if (mFinishOpenTransaction != null) {
- mFinishOpenTransaction.apply();
- mFinishOpenTransaction = null;
- }
- if (mFinishOpenTransitionCallback != null) {
- mFinishOpenTransitionCallback.onTransitionFinished(null);
- mFinishOpenTransitionCallback = null;
- }
mOpenTransitionInfo = null;
mPrepareOpenTransition = null;
+ if (mFinishOpenTransaction != null) {
+ final SurfaceControl.Transaction t = mFinishOpenTransaction;
+ mFinishOpenTransaction = null;
+ t.apply();
+ }
+ if (mFinishOpenTransitionCallback != null) {
+ final Transitions.TransitionFinishCallback callback = mFinishOpenTransitionCallback;
+ mFinishOpenTransitionCallback = null;
+ callback.onTransitionFinished(null);
+ }
}
private void applyAndFinish(@NonNull SurfaceControl.Transaction st,
@@ -1207,7 +1202,9 @@
@NonNull SurfaceControl.Transaction st,
@NonNull SurfaceControl.Transaction ft,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
- if (info.getType() == WindowManager.TRANSIT_PREPARE_BACK_NAVIGATION) {
+ final boolean isPrepareTransition =
+ info.getType() == WindowManager.TRANSIT_PREPARE_BACK_NAVIGATION;
+ if (isPrepareTransition) {
kickStartAnimation();
}
// Both mShellExecutor and Transitions#mMainExecutor are ShellMainThread, so we don't
@@ -1232,21 +1229,14 @@
}
if (mApps == null || mApps.length == 0) {
- if (mBackNavigationInfo != null && mShellBackAnimationRegistry
- .isWaitingAnimation(mBackNavigationInfo.getType())) {
- // Waiting for animation? Queue update to wait for animation start.
- consumeQueuedTransitionIfNeeded();
- mQueuedTransition = new QueuedTransition(info, st, ft, finishCallback);
- return true;
- } else if (mLastTrigger) {
- // animation was done, consume directly
+ if (mCloseTransitionRequested) {
+ // animation never start, consume directly
applyAndFinish(st, ft, finishCallback);
return true;
- } else {
- // animation was cancelled but transition haven't happen, we must handle it
- if (mClosePrepareTransition == null && mCurrentTracker.isFinished()) {
- createClosePrepareTransition();
- }
+ } else if (mClosePrepareTransition == null && isPrepareTransition) {
+ // Gesture animation was cancelled before prepare transition ready, create the
+ // the close prepare transition
+ createClosePrepareTransition();
}
}
@@ -1334,6 +1324,9 @@
tmpSize = init.getChanges().size();
for (int i = 0; i < tmpSize; ++i) {
final TransitionInfo.Change change = init.getChanges().get(i);
+ if (change.hasFlags(FLAG_IS_WALLPAPER)) {
+ continue;
+ }
if (moveToTop) {
if (isSameChangeTarget(openComponent, openTaskId, openToken, change)) {
change.setFlags(change.getFlags() | FLAG_MOVED_TO_TOP);
@@ -1390,14 +1383,18 @@
mergePendingTransitions(info);
}
+ if (info.getType() == TRANSIT_CLOSE_PREPARE_BACK_NAVIGATION
+ && !mCloseTransitionRequested && info.getChanges().isEmpty() && mApps != null) {
+ // Wait for post animation finish
+ finishCallback.onTransitionFinished(null);
+ t.apply();
+ return;
+ }
if (isNotGestureBackTransition(info) || shouldCancelAnimation(info)
|| !mCloseTransitionRequested) {
if (mPrepareOpenTransition != null) {
applyFinishOpenTransition();
}
- if (mQueuedTransition != null) {
- consumeQueuedTransitionIfNeeded();
- }
return;
}
// Handle the commit transition if this handler is running the open transition.
@@ -1405,11 +1402,9 @@
t.apply();
if (mCloseTransitionRequested) {
if (mApps == null || mApps.length == 0) {
- if (mQueuedTransition == null) {
- // animation was done
- applyFinishOpenTransition();
- mCloseTransitionRequested = false;
- } // let queued transition finish.
+ // animation was done
+ applyFinishOpenTransition();
+ mCloseTransitionRequested = false;
} else {
// we are animating, wait until animation finish
mOnAnimationFinishCallback = () -> {
@@ -1497,15 +1492,28 @@
}
}
if (openingLeash != null) {
+ int rootIdx = -1;
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change c = info.getChanges().get(i);
+ if (c.hasFlags(FLAG_IS_WALLPAPER)) {
+ st.setAlpha(c.getLeash(), 1.0f);
+ continue;
+ }
if (TransitionUtil.isOpeningMode(c.getMode())) {
final Point offset = c.getEndRelOffset();
st.setPosition(c.getLeash(), offset.x, offset.y);
st.reparent(c.getLeash(), openingLeash);
st.setAlpha(c.getLeash(), 1.0f);
+ rootIdx = TransitionUtil.rootIndexFor(c, info);
}
}
+ // The root leash and the leash of opening target should actually in the same level,
+ // but since the root leash is created after opening target, it will have higher
+ // layer in surface flinger. Move the root leash to lower level, so it won't affect
+ // the playing animation.
+ if (rootIdx >= 0 && info.getRootCount() > 0) {
+ st.setLayer(info.getRoot(rootIdx).getLeash(), -1);
+ }
}
st.apply();
mFinishOpenTransaction = ft;
@@ -1548,6 +1556,10 @@
if (openingLeash != null && closingLeash != null) {
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change c = info.getChanges().get(i);
+ if (c.hasFlags(FLAG_IS_WALLPAPER)) {
+ st.setAlpha(c.getLeash(), 1.0f);
+ continue;
+ }
if (TransitionUtil.isOpeningMode(c.getMode())) {
final Point offset = c.getEndRelOffset();
st.setPosition(c.getLeash(), offset.x, offset.y);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java
index 6fafa75..ae2c7b3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java
@@ -23,6 +23,8 @@
import android.util.SparseArray;
import android.window.BackNavigationInfo;
+import java.util.ArrayList;
+
/** Registry for all types of default back animations */
public class ShellBackAnimationRegistry {
private static final String TAG = "ShellBackPreview";
@@ -31,6 +33,8 @@
private ShellBackAnimation mDefaultCrossActivityAnimation;
private final ShellBackAnimation mCustomizeActivityAnimation;
private final ShellBackAnimation mCrossTaskAnimation;
+ private boolean mSupportedAnimatorsChanged = false;
+ private final ArrayList<Integer> mSupportedAnimators = new ArrayList<>();
public ShellBackAnimationRegistry(
@ShellBackAnimation.CrossActivity @Nullable ShellBackAnimation crossActivityAnimation,
@@ -60,7 +64,7 @@
mDefaultCrossActivityAnimation = crossActivityAnimation;
mCustomizeActivityAnimation = customizeActivityAnimation;
mCrossTaskAnimation = crossTaskAnimation;
-
+ updateSupportedAnimators();
// TODO(b/236760237): register dialog close animation when it's completed.
}
@@ -71,6 +75,7 @@
if (BackNavigationInfo.TYPE_CROSS_ACTIVITY == type) {
mDefaultCrossActivityAnimation = null;
}
+ updateSupportedAnimators();
}
void unregisterAnimation(@BackNavigationInfo.BackTargetType int type) {
@@ -79,6 +84,24 @@
if (BackNavigationInfo.TYPE_CROSS_ACTIVITY == type) {
mDefaultCrossActivityAnimation = null;
}
+ updateSupportedAnimators();
+ }
+
+ private void updateSupportedAnimators() {
+ mSupportedAnimators.clear();
+ for (int i = mAnimationDefinition.size() - 1; i >= 0; --i) {
+ mSupportedAnimators.add(mAnimationDefinition.keyAt(i));
+ }
+ mSupportedAnimatorsChanged = true;
+ }
+
+ boolean hasSupportedAnimatorsChanged() {
+ return mSupportedAnimatorsChanged;
+ }
+
+ ArrayList<Integer> getSupportedAnimators() {
+ mSupportedAnimatorsChanged = false;
+ return mSupportedAnimators;
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index 0c95934..169361a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -609,7 +609,8 @@
callback.onBubbleViewsReady(bubble);
}
},
- mMainExecutor);
+ mMainExecutor,
+ mBgExecutor);
if (mInflateSynchronously) {
mInflationTaskLegacy.onPostExecute(mInflationTaskLegacy.doInBackground());
} else {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
index f32974e..68c4657 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt
@@ -80,7 +80,10 @@
expandedViewManager,
positioner,
/* isOverflow= */ true,
- /* bubbleTaskView= */ null
+ /* bubbleTaskView= */ null,
+ /* mainExecutor= */ null,
+ /* backgroundExecutor= */ null,
+ /* regionSamplingProvider= */ null
)
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java
index 5f8f0fd..0c0fd7b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java
@@ -60,6 +60,9 @@
/** Called when back is pressed on the task root. */
void onBackPressed();
+
+ /** Called when task removal has started. */
+ void onTaskRemovalStarted();
}
private final Context mContext;
@@ -190,6 +193,7 @@
((ViewGroup) mParentView).removeView(mTaskView);
mTaskView = null;
}
+ mListener.onTaskRemovalStarted();
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
index 13855f7..3982a23 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
@@ -38,6 +38,7 @@
import android.util.Log;
import android.util.PathParser;
import android.view.LayoutInflater;
+import android.view.View;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.ColorUtils;
@@ -47,6 +48,7 @@
import com.android.wm.shell.R;
import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView;
import com.android.wm.shell.bubbles.bar.BubbleBarLayerView;
+import com.android.wm.shell.shared.handles.RegionSamplingHelper;
import java.lang.ref.WeakReference;
import java.util.Objects;
@@ -222,7 +224,16 @@
ProtoLog.v(WM_SHELL_BUBBLES, "Task initializing bubble bar expanded view key=%s",
mBubble.getKey());
viewInfo.bubbleBarExpandedView.initialize(mExpandedViewManager.get(),
- mPositioner.get(), false /* isOverflow */, viewInfo.taskView);
+ mPositioner.get(), false /* isOverflow */, viewInfo.taskView,
+ mMainExecutor, mBgExecutor, new RegionSamplingProvider() {
+ @Override
+ public RegionSamplingHelper createHelper(View sampledView,
+ RegionSamplingHelper.SamplingCallback callback,
+ Executor backgroundExecutor, Executor mainExecutor) {
+ return RegionSamplingProvider.super.createHelper(sampledView,
+ callback, backgroundExecutor, mainExecutor);
+ }
+ });
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java
index 5cfebf8..1b7bb0d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java
@@ -38,6 +38,7 @@
import android.util.Log;
import android.util.PathParser;
import android.view.LayoutInflater;
+import android.view.View;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.ColorUtils;
@@ -46,6 +47,7 @@
import com.android.wm.shell.R;
import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView;
import com.android.wm.shell.bubbles.bar.BubbleBarLayerView;
+import com.android.wm.shell.shared.handles.RegionSamplingHelper;
import java.lang.ref.WeakReference;
import java.util.Objects;
@@ -85,6 +87,7 @@
private boolean mSkipInflation;
private Callback mCallback;
private Executor mMainExecutor;
+ private Executor mBackgroundExecutor;
/**
* Creates a task to load information for the provided {@link Bubble}. Once all info
@@ -100,7 +103,8 @@
BubbleIconFactory factory,
boolean skipInflation,
Callback c,
- Executor mainExecutor) {
+ Executor mainExecutor,
+ Executor backgroundExecutor) {
mBubble = b;
mContext = new WeakReference<>(context);
mExpandedViewManager = new WeakReference<>(expandedViewManager);
@@ -112,6 +116,7 @@
mSkipInflation = skipInflation;
mCallback = c;
mMainExecutor = mainExecutor;
+ mBackgroundExecutor = backgroundExecutor;
}
@Override
@@ -123,7 +128,7 @@
if (mLayerView.get() != null) {
return BubbleViewInfo.populateForBubbleBar(mContext.get(), mExpandedViewManager.get(),
mTaskViewFactory.get(), mPositioner.get(), mLayerView.get(), mIconFactory,
- mBubble, mSkipInflation);
+ mBubble, mSkipInflation, mMainExecutor, mBackgroundExecutor);
} else {
return BubbleViewInfo.populate(mContext.get(), mExpandedViewManager.get(),
mTaskViewFactory.get(), mPositioner.get(), mStackView.get(), mIconFactory,
@@ -188,7 +193,9 @@
BubbleBarLayerView layerView,
BubbleIconFactory iconFactory,
Bubble b,
- boolean skipInflation) {
+ boolean skipInflation,
+ Executor mainExecutor,
+ Executor backgroundExecutor) {
BubbleViewInfo info = new BubbleViewInfo();
if (!skipInflation && !b.isInflated()) {
@@ -197,7 +204,16 @@
info.bubbleBarExpandedView = (BubbleBarExpandedView) inflater.inflate(
R.layout.bubble_bar_expanded_view, layerView, false /* attachToRoot */);
info.bubbleBarExpandedView.initialize(
- expandedViewManager, positioner, false /* isOverflow */, bubbleTaskView);
+ expandedViewManager, positioner, false /* isOverflow */, bubbleTaskView,
+ mainExecutor, backgroundExecutor, new RegionSamplingProvider() {
+ @Override
+ public RegionSamplingHelper createHelper(View sampledView,
+ RegionSamplingHelper.SamplingCallback callback,
+ Executor backgroundExecutor, Executor mainExecutor) {
+ return RegionSamplingProvider.super.createHelper(sampledView,
+ callback, backgroundExecutor, mainExecutor);
+ }
+ });
}
if (!populateCommonInfo(info, c, b, iconFactory)) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/RegionSamplingProvider.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/RegionSamplingProvider.java
new file mode 100644
index 0000000..30f5c8fd
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/RegionSamplingProvider.java
@@ -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.wm.shell.bubbles;
+
+import android.view.View;
+
+import com.android.wm.shell.shared.handles.RegionSamplingHelper;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Wrapper to provide a {@link com.android.wm.shell.shared.handles.RegionSamplingHelper} to allow
+ * testing it.
+ */
+public interface RegionSamplingProvider {
+
+ /** Creates and returns the region sampling helper */
+ default RegionSamplingHelper createHelper(View sampledView,
+ RegionSamplingHelper.SamplingCallback callback,
+ Executor backgroundExecutor,
+ Executor mainExecutor) {
+ return new RegionSamplingHelper(sampledView,
+ callback, backgroundExecutor, mainExecutor);
+ }
+
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
index 565fde0..74c3748 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
@@ -253,6 +253,7 @@
return;
}
setDragPivot(bbev);
+ bbev.setDragging(true);
// Corner radius gets scaled, apply the reverse scale to ensure we have the desired radius
final float cornerRadius = bbev.getDraggedCornerRadius() / EXPANDED_VIEW_DRAG_SCALE;
@@ -329,6 +330,7 @@
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
bbev.resetPivot();
+ bbev.setDragging(false);
}
});
startNewDragAnimation(animatorSet);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
index f90b2aa..ec235a5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
@@ -19,10 +19,7 @@
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import android.annotation.Nullable;
-import android.app.ActivityManager;
import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Color;
import android.graphics.Insets;
import android.graphics.Outline;
import android.graphics.Rect;
@@ -37,6 +34,7 @@
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
import com.android.wm.shell.R;
import com.android.wm.shell.bubbles.Bubble;
@@ -46,9 +44,12 @@
import com.android.wm.shell.bubbles.BubbleTaskView;
import com.android.wm.shell.bubbles.BubbleTaskViewHelper;
import com.android.wm.shell.bubbles.Bubbles;
+import com.android.wm.shell.bubbles.RegionSamplingProvider;
import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
+import com.android.wm.shell.shared.handles.RegionSamplingHelper;
import com.android.wm.shell.taskview.TaskView;
+import java.util.concurrent.Executor;
import java.util.function.Supplier;
/** Expanded view of a bubble when it's part of the bubble bar. */
@@ -92,16 +93,35 @@
private boolean mIsOverflow;
private BubbleTaskViewHelper mBubbleTaskViewHelper;
private BubbleBarMenuViewController mMenuViewController;
- private @Nullable Supplier<Rect> mLayerBoundsSupplier;
- private @Nullable Listener mListener;
+ @Nullable
+ private Supplier<Rect> mLayerBoundsSupplier;
+ @Nullable
+ private Listener mListener;
private BubbleBarHandleView mHandleView;
- private @Nullable TaskView mTaskView;
- private @Nullable BubbleOverflowContainerView mOverflowView;
+ @Nullable
+ private TaskView mTaskView;
+ @Nullable
+ private BubbleOverflowContainerView mOverflowView;
+ /**
+ * The handle shown in the caption area is tinted based on the background color of the area.
+ * This can vary so we sample the caption region and update the handle color based on that.
+ * If we're showing the overflow, the helper and executors will be null.
+ */
+ @Nullable
+ private RegionSamplingHelper mRegionSamplingHelper;
+ @Nullable
+ private RegionSamplingProvider mRegionSamplingProvider;
+ @Nullable
+ private Executor mMainExecutor;
+ @Nullable
+ private Executor mBackgroundExecutor;
+ private final Rect mSampleRect = new Rect();
+ private final int[] mLoc = new int[2];
+
+ /** Height of the caption inset at the top of the TaskView */
private int mCaptionHeight;
-
- private int mBackgroundColor;
/** Corner radius used when view is resting */
private float mRestingCornerRadius = 0f;
/** Corner radius applied while dragging */
@@ -116,6 +136,7 @@
*/
private boolean mIsContentVisible = false;
private boolean mIsAnimating;
+ private boolean mIsDragging;
public BubbleBarExpandedView(Context context) {
this(context, null);
@@ -154,21 +175,20 @@
setOnTouchListener((v, event) -> true);
}
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- // Hide manage menu when view disappears
- mMenuViewController.hideMenu(false /* animated */);
- }
-
/** Initializes the view, must be called before doing anything else. */
public void initialize(BubbleExpandedViewManager expandedViewManager,
BubblePositioner positioner,
boolean isOverflow,
- @Nullable BubbleTaskView bubbleTaskView) {
+ @Nullable BubbleTaskView bubbleTaskView,
+ @Nullable Executor mainExecutor,
+ @Nullable Executor backgroundExecutor,
+ @Nullable RegionSamplingProvider regionSamplingProvider) {
mManager = expandedViewManager;
mPositioner = positioner;
mIsOverflow = isOverflow;
+ mMainExecutor = mainExecutor;
+ mBackgroundExecutor = backgroundExecutor;
+ mRegionSamplingProvider = regionSamplingProvider;
if (mIsOverflow) {
mOverflowView = (BubbleOverflowContainerView) LayoutInflater.from(getContext()).inflate(
@@ -191,6 +211,7 @@
mTaskView.setEnableSurfaceClipping(true);
mTaskView.setCornerRadius(mCurrentCornerRadius);
mTaskView.setVisibility(VISIBLE);
+ mTaskView.setCaptionInsets(Insets.of(0, mCaptionHeight, 0, 0));
// Handle view needs to draw on top of task view.
bringChildToFront(mHandleView);
@@ -245,32 +266,40 @@
return mHandleView;
}
- // TODO (b/275087636): call this when theme/config changes
/** Updates the view based on the current theme. */
public void applyThemeAttrs() {
+ mCaptionHeight = getResources().getDimensionPixelSize(
+ R.dimen.bubble_bar_expanded_view_caption_height);
mRestingCornerRadius = getResources().getDimensionPixelSize(
- R.dimen.bubble_bar_expanded_view_corner_radius
- );
+ R.dimen.bubble_bar_expanded_view_corner_radius);
mDraggedCornerRadius = getResources().getDimensionPixelSize(
- R.dimen.bubble_bar_expanded_view_corner_radius_dragged
- );
+ R.dimen.bubble_bar_expanded_view_corner_radius_dragged);
mCurrentCornerRadius = mRestingCornerRadius;
- final TypedArray ta = mContext.obtainStyledAttributes(new int[]{
- android.R.attr.colorBackgroundFloating});
- mBackgroundColor = ta.getColor(0, Color.WHITE);
- ta.recycle();
- mCaptionHeight = getResources().getDimensionPixelSize(
- R.dimen.bubble_bar_expanded_view_caption_height);
-
if (mTaskView != null) {
mTaskView.setCornerRadius(mCurrentCornerRadius);
- updateHandleColor(true /* animated */);
+ mTaskView.setCaptionInsets(Insets.of(0, mCaptionHeight, 0, 0));
}
}
@Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ // Hide manage menu when view disappears
+ mMenuViewController.hideMenu(false /* animated */);
+ if (mRegionSamplingHelper != null) {
+ mRegionSamplingHelper.stopAndDestroy();
+ }
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ recreateRegionSamplingHelper();
+ }
+
+ @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mTaskView != null) {
@@ -284,16 +313,13 @@
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (mTaskView != null) {
- mTaskView.layout(l, t, r,
- t + mTaskView.getMeasuredHeight());
- mTaskView.setCaptionInsets(Insets.of(0, mCaptionHeight, 0, 0));
+ mTaskView.layout(l, t, r, t + mTaskView.getMeasuredHeight());
}
}
@Override
public void onTaskCreated() {
setContentVisibility(true);
- updateHandleColor(false /* animated */);
if (mListener != null) {
mListener.onTaskCreated();
}
@@ -305,11 +331,70 @@
}
@Override
+ public void onTaskRemovalStarted() {
+ if (mRegionSamplingHelper != null) {
+ mRegionSamplingHelper.stopAndDestroy();
+ }
+ }
+
+ @Override
public void onBackPressed() {
if (mListener == null) return;
mListener.onBackPressed();
}
+ /**
+ * Set whether this view is currently being dragged.
+ *
+ * When dragging, the handle is hidden and content shouldn't be sampled. When dragging has
+ * ended we should start again.
+ */
+ public void setDragging(boolean isDragging) {
+ if (isDragging != mIsDragging) {
+ mIsDragging = isDragging;
+ updateSamplingState();
+ }
+ }
+
+ /** Returns whether region sampling should be enabled, i.e. if task view content is visible. */
+ private boolean shouldSampleRegion() {
+ return mTaskView != null
+ && mTaskView.getTaskInfo() != null
+ && !mIsDragging
+ && !mIsAnimating
+ && mIsContentVisible;
+ }
+
+ /**
+ * Handles starting or stopping the region sampling helper based on
+ * {@link #shouldSampleRegion()}.
+ */
+ private void updateSamplingState() {
+ if (mRegionSamplingHelper == null) return;
+ boolean shouldSample = shouldSampleRegion();
+ if (shouldSample) {
+ mRegionSamplingHelper.start(getCaptionSampleRect());
+ } else {
+ mRegionSamplingHelper.stop();
+ }
+ }
+
+ /** Returns the current area of the caption bar, in screen coordinates. */
+ Rect getCaptionSampleRect() {
+ if (mTaskView == null) return null;
+ mTaskView.getLocationOnScreen(mLoc);
+ mSampleRect.set(mLoc[0], mLoc[1],
+ mLoc[0] + mTaskView.getWidth(),
+ mLoc[1] + mCaptionHeight);
+ return mSampleRect;
+ }
+
+ @VisibleForTesting
+ @Nullable
+ public RegionSamplingHelper getRegionSamplingHelper() {
+ return mRegionSamplingHelper;
+ }
+
/** Cleans up the expanded view, should be called when the bubble is no longer active. */
public void cleanUpExpandedState() {
mMenuViewController.hideMenu(false /* animated */);
@@ -394,27 +479,14 @@
if (!mIsAnimating) {
mTaskView.setAlpha(visible ? 1f : 0f);
+ if (mRegionSamplingHelper != null) {
+ mRegionSamplingHelper.setWindowVisible(visible);
+ }
+ updateSamplingState();
}
}
/**
- * Updates the handle color based on the task view status bar or background color; if those
- * are transparent it defaults to the background color pulled from system theme attributes.
- */
- private void updateHandleColor(boolean animated) {
- if (mTaskView == null || mTaskView.getTaskInfo() == null) return;
- int color = mBackgroundColor;
- ActivityManager.TaskDescription taskDescription = mTaskView.getTaskInfo().taskDescription;
- if (taskDescription.getStatusBarColor() != Color.TRANSPARENT) {
- color = taskDescription.getStatusBarColor();
- } else if (taskDescription.getBackgroundColor() != Color.TRANSPARENT) {
- color = taskDescription.getBackgroundColor();
- }
- final boolean isRegionDark = Color.luminance(color) <= 0.5;
- mHandleView.updateHandleColor(isRegionDark, animated);
- }
-
- /**
* Sets the alpha of both this view and the task view.
*/
public void setTaskViewAlpha(float alpha) {
@@ -442,6 +514,11 @@
*/
public void setAnimating(boolean animating) {
mIsAnimating = animating;
+ if (mIsAnimating) {
+ // Stop sampling while animating -- when animating is done setContentVisibility will
+ // re-trigger sampling if we're visible.
+ updateSamplingState();
+ }
// If we're done animating, apply the correct visibility.
if (!animating) {
setContentVisibility(mIsContentVisible);
@@ -481,6 +558,37 @@
}
}
+ private void recreateRegionSamplingHelper() {
+ if (mRegionSamplingHelper != null) {
+ mRegionSamplingHelper.stopAndDestroy();
+ }
+ if (mMainExecutor == null || mBackgroundExecutor == null
+ || mRegionSamplingProvider == null) {
+ // Null when it's the overflow / don't need sampling then.
+ return;
+ }
+ mRegionSamplingHelper = mRegionSamplingProvider.createHelper(this,
+ new RegionSamplingHelper.SamplingCallback() {
+ @Override
+ public void onRegionDarknessChanged(boolean isRegionDark) {
+ if (mHandleView != null) {
+ mHandleView.updateHandleColor(isRegionDark,
+ true /* animated */);
+ }
+ }
+
+ @Override
+ public Rect getSampledRegion(View sampledView) {
+ return getCaptionSampleRect();
+ }
+
+ @Override
+ public boolean isSamplingEnabled() {
+ return shouldSampleRegion();
+ }
+ }, mMainExecutor, mBackgroundExecutor);
+ }
+
private class HandleViewAccessibilityDelegate extends AccessibilityDelegate {
@Override
public void onInitializeAccessibilityNodeInfo(@NonNull View host,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java
index c91567d..e781c07 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarHandleView.java
@@ -42,7 +42,9 @@
private final @ColorInt int mHandleLightColor;
private final @ColorInt int mHandleDarkColor;
- private @Nullable ObjectAnimator mColorChangeAnim;
+ private @ColorInt int mCurrentColor;
+ @Nullable
+ private ObjectAnimator mColorChangeAnim;
public BubbleBarHandleView(Context context) {
this(context, null /* attrs */);
@@ -88,13 +90,17 @@
*
* @param isRegionDark Whether the background behind the handle is dark, and thus the handle
* should be light (and vice versa).
- * @param animated Whether to animate the change, or apply it immediately.
+ * @param animated Whether to animate the change, or apply it immediately.
*/
public void updateHandleColor(boolean isRegionDark, boolean animated) {
int newColor = isRegionDark ? mHandleLightColor : mHandleDarkColor;
+ if (newColor == mCurrentColor) {
+ return;
+ }
if (mColorChangeAnim != null) {
mColorChangeAnim.cancel();
}
+ mCurrentColor = newColor;
if (animated) {
mColorChangeAnim = ObjectAnimator.ofArgb(this, "backgroundColor", newColor);
mColorChangeAnim.addListener(new AnimatorListenerAdapter() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
index 5b01a0d..f03daad 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
@@ -291,17 +291,11 @@
if (hadImeSourceControl != hasImeSourceControl) {
dispatchImeControlTargetChanged(mDisplayId, hasImeSourceControl);
}
+ final boolean hasImeLeash = hasImeSourceControl && imeSourceControl.getLeash() != null;
boolean pendingImeStartAnimation = false;
- boolean canAnimate;
- if (android.view.inputmethod.Flags.refactorInsetsController()) {
- canAnimate = hasImeSourceControl && imeSourceControl.getLeash() != null;
- } else {
- canAnimate = hasImeSourceControl;
- }
-
boolean positionChanged = false;
- if (canAnimate) {
+ if (hasImeLeash) {
if (mAnimation != null) {
final Point lastSurfacePosition = hadImeSourceControl
? mImeSourceControl.getSurfacePosition() : null;
@@ -325,6 +319,13 @@
// continue the bar to slide to the end (even without visible IME)
mAnimation.cancel();
}
+
+ // Make mImeSourceControl point to the new control before starting the animation.
+ if (hadImeSourceControl && mImeSourceControl != imeSourceControl) {
+ mImeSourceControl.release(SurfaceControl::release);
+ }
+ mImeSourceControl = imeSourceControl;
+
if (positionChanged) {
if (android.view.inputmethod.Flags.refactorInsetsController()) {
// For showing the IME, the leash has to be available first. Hiding
@@ -338,11 +339,6 @@
}
}
- if (hadImeSourceControl && mImeSourceControl != imeSourceControl) {
- mImeSourceControl.release(SurfaceControl::release);
- }
- mImeSourceControl = imeSourceControl;
-
if (android.view.inputmethod.Flags.refactorInsetsController()) {
if (pendingImeStartAnimation) {
startAnimation(true, true /* forceRestart */);
@@ -465,11 +461,12 @@
private void startAnimation(final boolean show, final boolean forceRestart,
@NonNull final ImeTracker.Token statsToken) {
+ if (mImeSourceControl == null || mImeSourceControl.getLeash() == null) {
+ if (DEBUG) Slog.d(TAG, "No leash available, not starting the animation.");
+ return;
+ }
if (android.view.inputmethod.Flags.refactorInsetsController()) {
- if (mImeSourceControl == null || mImeSourceControl.getLeash() == null) {
- if (DEBUG) Slog.d(TAG, "No leash available, not starting the animation.");
- return;
- } else if (!mImeRequestedVisible && show) {
+ if (!mImeRequestedVisible && show) {
// we have a control with leash, but the IME was not requested visible before,
// therefore aborting the show animation.
Slog.e(TAG, "IME was not requested visible, not starting the show animation.");
@@ -478,7 +475,7 @@
}
}
final InsetsSource imeSource = mInsetsState.peekSource(InsetsSource.ID_IME);
- if (imeSource == null || mImeSourceControl == null) {
+ if (imeSource == null) {
ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
return;
}
@@ -515,8 +512,10 @@
}
mAnimation.cancel();
}
- final float defaultY = mImeSourceControl.getSurfacePosition().y;
- final float x = mImeSourceControl.getSurfacePosition().x;
+ final InsetsSourceControl animatingControl = new InsetsSourceControl(mImeSourceControl);
+ final SurfaceControl animatingLeash = animatingControl.getLeash();
+ final float defaultY = animatingControl.getSurfacePosition().y;
+ final float x = animatingControl.getSurfacePosition().x;
final float hiddenY = defaultY + mImeFrame.height();
final float shownY = defaultY;
final float startY = show ? hiddenY : shownY;
@@ -538,13 +537,10 @@
mAnimation.addUpdateListener(animation -> {
SurfaceControl.Transaction t = mTransactionPool.acquire();
float value = (float) animation.getAnimatedValue();
- if (!android.view.inputmethod.Flags.refactorInsetsController() || (
- mImeSourceControl != null && mImeSourceControl.getLeash() != null)) {
- t.setPosition(mImeSourceControl.getLeash(), x, value);
- final float alpha = (mAnimateAlpha || isFloating)
- ? (value - hiddenY) / (shownY - hiddenY) : 1.f;
- t.setAlpha(mImeSourceControl.getLeash(), alpha);
- }
+ t.setPosition(animatingLeash, x, value);
+ final float alpha = (mAnimateAlpha || isFloating)
+ ? (value - hiddenY) / (shownY - hiddenY) : 1f;
+ t.setAlpha(animatingLeash, alpha);
dispatchPositionChanged(mDisplayId, imeTop(value), t);
t.apply();
mTransactionPool.release(t);
@@ -561,7 +557,7 @@
ValueAnimator valueAnimator = (ValueAnimator) animation;
float value = (float) valueAnimator.getAnimatedValue();
SurfaceControl.Transaction t = mTransactionPool.acquire();
- t.setPosition(mImeSourceControl.getLeash(), x, value);
+ t.setPosition(animatingLeash, x, value);
if (DEBUG) {
Slog.d(TAG, "onAnimationStart d:" + mDisplayId + " top:"
+ imeTop(hiddenY) + "->" + imeTop(shownY)
@@ -573,19 +569,19 @@
final float alpha = (mAnimateAlpha || isFloating)
? (value - hiddenY) / (shownY - hiddenY)
: 1.f;
- t.setAlpha(mImeSourceControl.getLeash(), alpha);
+ t.setAlpha(animatingLeash, alpha);
if (mAnimationDirection == DIRECTION_SHOW) {
ImeTracker.forLogging().onProgress(mStatsToken,
ImeTracker.PHASE_WM_ANIMATION_RUNNING);
- t.show(mImeSourceControl.getLeash());
+ t.show(animatingLeash);
}
if (DEBUG_IME_VISIBILITY) {
EventLog.writeEvent(IMF_IME_REMOTE_ANIM_START,
mStatsToken != null ? mStatsToken.getTag() : ImeTracker.TOKEN_NONE,
mDisplayId, mAnimationDirection, alpha, value, endY,
- Objects.toString(mImeSourceControl.getLeash()),
- Objects.toString(mImeSourceControl.getInsetsHint()),
- Objects.toString(mImeSourceControl.getSurfacePosition()),
+ Objects.toString(animatingLeash),
+ Objects.toString(animatingControl.getInsetsHint()),
+ Objects.toString(animatingControl.getSurfacePosition()),
Objects.toString(mImeFrame));
}
t.apply();
@@ -599,31 +595,23 @@
EventLog.writeEvent(IMF_IME_REMOTE_ANIM_CANCEL,
mStatsToken != null ? mStatsToken.getTag() : ImeTracker.TOKEN_NONE,
mDisplayId,
- Objects.toString(mImeSourceControl.getInsetsHint()));
+ Objects.toString(animatingControl.getInsetsHint()));
}
}
@Override
public void onAnimationEnd(Animator animation) {
- boolean hasLeash =
- mImeSourceControl != null && mImeSourceControl.getLeash() != null;
if (DEBUG) Slog.d(TAG, "onAnimationEnd " + mCancelled);
SurfaceControl.Transaction t = mTransactionPool.acquire();
if (!mCancelled) {
- if (!android.view.inputmethod.Flags.refactorInsetsController()
- || hasLeash) {
- t.setPosition(mImeSourceControl.getLeash(), x, endY);
- t.setAlpha(mImeSourceControl.getLeash(), 1.f);
- }
+ t.setPosition(animatingLeash, x, endY);
+ t.setAlpha(animatingLeash, 1.f);
}
dispatchEndPositioning(mDisplayId, mCancelled, t);
if (mAnimationDirection == DIRECTION_HIDE && !mCancelled) {
ImeTracker.forLogging().onProgress(mStatsToken,
ImeTracker.PHASE_WM_ANIMATION_RUNNING);
- if (!android.view.inputmethod.Flags.refactorInsetsController()
- || hasLeash) {
- t.hide(mImeSourceControl.getLeash());
- }
+ t.hide(animatingLeash);
removeImeSurface(mDisplayId);
ImeTracker.forLogging().onHidden(mStatsToken);
} else if (mAnimationDirection == DIRECTION_SHOW && !mCancelled) {
@@ -636,13 +624,9 @@
EventLog.writeEvent(IMF_IME_REMOTE_ANIM_END,
mStatsToken != null ? mStatsToken.getTag() : ImeTracker.TOKEN_NONE,
mDisplayId, mAnimationDirection, endY,
- Objects.toString(
- mImeSourceControl != null ? mImeSourceControl.getLeash()
- : "null"),
- Objects.toString(mImeSourceControl != null
- ? mImeSourceControl.getInsetsHint() : "null"),
- Objects.toString(mImeSourceControl != null
- ? mImeSourceControl.getSurfacePosition() : "null"),
+ Objects.toString(animatingLeash),
+ Objects.toString(animatingControl.getInsetsHint()),
+ Objects.toString(animatingControl.getSurfacePosition()),
Objects.toString(mImeFrame));
}
t.apply();
@@ -650,6 +634,7 @@
mAnimationDirection = DIRECTION_NONE;
mAnimation = null;
+ animatingControl.release(SurfaceControl::release);
}
});
if (!show) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java
index 4b138e4..dd17e29 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java
@@ -17,7 +17,6 @@
package com.android.wm.shell.common;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
/**
* Helpers for handling surface.
@@ -25,16 +24,15 @@
public class SurfaceUtils {
/** Creates a dim layer above host surface. */
public static SurfaceControl makeDimLayer(SurfaceControl.Transaction t, SurfaceControl host,
- String name, SurfaceSession surfaceSession) {
- final SurfaceControl dimLayer = makeColorLayer(host, name, surfaceSession);
+ String name) {
+ final SurfaceControl dimLayer = makeColorLayer(host, name);
t.setLayer(dimLayer, Integer.MAX_VALUE).setColor(dimLayer, new float[]{0f, 0f, 0f});
return dimLayer;
}
/** Creates a color layer for host surface. */
- public static SurfaceControl makeColorLayer(SurfaceControl host, String name,
- SurfaceSession surfaceSession) {
- return new SurfaceControl.Builder(surfaceSession)
+ public static SurfaceControl makeColorLayer(SurfaceControl host, String name) {
+ return new SurfaceControl.Builder()
.setParent(host)
.setColorLayer()
.setName(name)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index ef33b38..3dc86de 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -42,7 +42,6 @@
import android.view.ScrollCaptureResponse;
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
-import android.view.SurfaceSession;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -311,7 +310,7 @@
@Override
protected SurfaceControl getParentSurface(IWindow window,
WindowManager.LayoutParams attrs) {
- SurfaceControl leash = new SurfaceControl.Builder(new SurfaceSession())
+ SurfaceControl leash = new SurfaceControl.Builder()
.setContainerLayer()
.setName("SystemWindowLeash")
.setHidden(false)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt
index dcf84d9..7070ce9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt
@@ -24,7 +24,6 @@
import android.content.pm.PackageManager
import android.graphics.Rect
import android.os.RemoteException
-import android.os.SystemProperties
import android.util.DisplayMetrics
import android.util.Log
import android.util.Pair
@@ -178,9 +177,7 @@
"org.chromium.arc", 0)
val isTv = AppGlobals.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_LEANBACK, 0)
- isPip2ExperimentEnabled = SystemProperties.getBoolean(
- "persist.wm_shell.pip2", false) ||
- (Flags.enablePip2Implementation() && !isArc && !isTv)
+ isPip2ExperimentEnabled = Flags.enablePip2() && !isArc && !isTv
}
return isPip2ExperimentEnabled as Boolean
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
index 7175e36..de3152a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
@@ -43,7 +43,6 @@
import android.view.LayoutInflater;
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
-import android.view.SurfaceSession;
import android.view.View;
import android.view.WindowManager;
import android.view.WindowlessWindowManager;
@@ -74,7 +73,6 @@
private static final String GAP_BACKGROUND_SURFACE_NAME = "GapBackground";
private final IconProvider mIconProvider;
- private final SurfaceSession mSurfaceSession;
private Drawable mIcon;
private ImageView mVeilIconView;
@@ -103,17 +101,15 @@
private int mOffsetY;
private int mRunningAnimationCount = 0;
- public SplitDecorManager(Configuration configuration, IconProvider iconProvider,
- SurfaceSession surfaceSession) {
+ public SplitDecorManager(Configuration configuration, IconProvider iconProvider) {
super(configuration, null /* rootSurface */, null /* hostInputToken */);
mIconProvider = iconProvider;
- mSurfaceSession = surfaceSession;
}
@Override
protected SurfaceControl getParentSurface(IWindow window, WindowManager.LayoutParams attrs) {
// Can't set position for the ViewRootImpl SC directly. Create a leash to manipulate later.
- final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
+ final SurfaceControl.Builder builder = new SurfaceControl.Builder()
.setContainerLayer()
.setName(TAG)
.setHidden(true)
@@ -238,7 +234,7 @@
if (mBackgroundLeash == null) {
mBackgroundLeash = SurfaceUtils.makeColorLayer(mHostLeash,
- RESIZING_BACKGROUND_SURFACE_NAME, mSurfaceSession);
+ RESIZING_BACKGROUND_SURFACE_NAME);
t.setColor(mBackgroundLeash, getResizingBackgroundColor(resizingTask))
.setLayer(mBackgroundLeash, Integer.MAX_VALUE - 1);
}
@@ -248,7 +244,7 @@
final int left = isLandscape ? mOldMainBounds.width() : 0;
final int top = isLandscape ? 0 : mOldMainBounds.height();
mGapBackgroundLeash = SurfaceUtils.makeColorLayer(mHostLeash,
- GAP_BACKGROUND_SURFACE_NAME, mSurfaceSession);
+ GAP_BACKGROUND_SURFACE_NAME);
// Fill up another side bounds area.
t.setColor(mGapBackgroundLeash, getResizingBackgroundColor(resizingTask))
.setLayer(mGapBackgroundLeash, Integer.MAX_VALUE - 2)
@@ -405,7 +401,7 @@
if (mBackgroundLeash == null) {
// Initialize background
mBackgroundLeash = SurfaceUtils.makeColorLayer(mHostLeash,
- RESIZING_BACKGROUND_SURFACE_NAME, mSurfaceSession);
+ RESIZING_BACKGROUND_SURFACE_NAME);
t.setColor(mBackgroundLeash, getResizingBackgroundColor(resizingTask))
.setLayer(mBackgroundLeash, Integer.MAX_VALUE - 1);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index 46c1a43..c5f1974 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -36,7 +36,6 @@
import android.view.LayoutInflater;
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
-import android.view.SurfaceSession;
import android.view.WindowManager;
import android.view.WindowlessWindowManager;
@@ -98,7 +97,7 @@
@Override
protected SurfaceControl getParentSurface(IWindow window, WindowManager.LayoutParams attrs) {
// Can't set position for the ViewRootImpl SC directly. Create a leash to manipulate later.
- final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
+ final SurfaceControl.Builder builder = new SurfaceControl.Builder()
.setContainerLayer()
.setName(TAG)
.setHidden(true)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
index 972b78f..6146ecd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
@@ -831,7 +831,6 @@
*/
static class CompatUIHintsState {
boolean mHasShownSizeCompatHint;
- boolean mHasShownCameraCompatHint;
boolean mHasShownUserAspectRatioSettingsButtonHint;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
index 0564c95..d2b4f1a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
@@ -38,7 +38,6 @@
import android.view.IWindow;
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
-import android.view.SurfaceSession;
import android.view.View;
import android.view.WindowManager;
import android.view.WindowlessWindowManager;
@@ -173,7 +172,7 @@
@Override
protected SurfaceControl getParentSurface(IWindow window, WindowManager.LayoutParams attrs) {
String className = getClass().getSimpleName();
- final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
+ final SurfaceControl.Builder builder = new SurfaceControl.Builder()
.setContainerLayer()
.setName(className + "Leash")
.setHidden(false)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponent.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponent.kt
index 831b331..abc26cf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponent.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/api/CompatUIComponent.kt
@@ -24,7 +24,6 @@
import android.view.IWindow
import android.view.SurfaceControl
import android.view.SurfaceControlViewHost
-import android.view.SurfaceSession
import android.view.View
import android.view.WindowManager
import android.view.WindowlessWindowManager
@@ -106,7 +105,7 @@
attrs: WindowManager.LayoutParams
): SurfaceControl? {
val className = javaClass.simpleName
- val builder = SurfaceControl.Builder(SurfaceSession())
+ val builder = SurfaceControl.Builder()
.setContainerLayer()
.setName(className + "Leash")
.setHidden(false)
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 02ecfd9..7054c17c 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
@@ -38,6 +38,7 @@
import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.activityembedding.ActivityEmbeddingController;
import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser;
+import com.android.wm.shell.apptoweb.AssistContentRequester;
import com.android.wm.shell.bubbles.BubbleController;
import com.android.wm.shell.bubbles.BubbleData;
import com.android.wm.shell.bubbles.BubbleDataRepository;
@@ -240,6 +241,7 @@
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
InteractionJankMonitor interactionJankMonitor,
AppToWebGenericLinksParser genericLinksParser,
+ AssistContentRequester assistContentRequester,
MultiInstanceHelper multiInstanceHelper,
Optional<DesktopTasksLimiter> desktopTasksLimiter,
Optional<DesktopActivityOrientationChangeHandler> desktopActivityOrientationHandler) {
@@ -263,6 +265,7 @@
rootTaskDisplayAreaOrganizer,
interactionJankMonitor,
genericLinksParser,
+ assistContentRequester,
multiInstanceHelper,
desktopTasksLimiter,
desktopActivityOrientationHandler);
@@ -291,6 +294,15 @@
return new AppToWebGenericLinksParser(context, mainExecutor);
}
+ @Provides
+ static AssistContentRequester provideAssistContentRequester(
+ Context context,
+ @ShellMainThread ShellExecutor shellExecutor,
+ @ShellBackgroundThread ShellExecutor bgExecutor
+ ) {
+ return new AssistContentRequester(context, shellExecutor, bgExecutor);
+ }
+
//
// Freeform
//
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/BackgroundWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/BackgroundWindowManager.java
index 71cc8df..422656c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/BackgroundWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/BackgroundWindowManager.java
@@ -38,7 +38,6 @@
import android.view.LayoutInflater;
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
-import android.view.SurfaceSession;
import android.view.View;
import android.view.WindowManager;
import android.view.WindowlessWindowManager;
@@ -105,7 +104,7 @@
@Override
protected SurfaceControl getParentSurface(IWindow window, WindowManager.LayoutParams attrs) {
- final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
+ final SurfaceControl.Builder builder = new SurfaceControl.Builder()
.setColorLayer()
.setBufferSize(mDisplayBounds.width(), mDisplayBounds.height())
.setFormat(PixelFormat.RGB_888)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
index 39bea1b..9af33a8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
@@ -21,9 +21,12 @@
import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_RECENT_TASKS;
+import android.Manifest;
+import android.annotation.RequiresPermission;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.IApplicationThread;
+import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
@@ -158,6 +161,7 @@
return new IRecentTasksImpl(this);
}
+ @RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE)
private void onInit() {
mShellController.addExternalInterface(KEY_EXTRA_SHELL_RECENT_TASKS,
this::createExternalInterface, this);
@@ -168,6 +172,8 @@
mTaskStackTransitionObserver.addTaskStackTransitionObserverListener(this,
mMainExecutor);
}
+ mContext.getSystemService(KeyguardManager.class).addKeyguardLockedStateListener(
+ mMainExecutor, isKeyguardLocked -> notifyRecentTasksChanged());
}
void setTransitionHandler(RecentsTransitionHandler handler) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
deleted file mode 100644
index 1cbb8bb..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.splitscreen;
-
-import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN;
-
-import android.content.Context;
-import android.view.SurfaceSession;
-import android.window.WindowContainerToken;
-import android.window.WindowContainerTransaction;
-
-import com.android.internal.protolog.ProtoLog;
-import com.android.launcher3.icons.IconProvider;
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.windowdecor.WindowDecorViewModel;
-
-import java.util.Optional;
-
-/**
- * Main stage for split-screen mode. When split-screen is active all standard activity types launch
- * on the main stage, except for task that are explicitly pinned to the {@link SideStage}.
- * @see StageCoordinator
- */
-class MainStage extends StageTaskListener {
- private boolean mIsActive = false;
-
- MainStage(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
- StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
- SurfaceSession surfaceSession, IconProvider iconProvider,
- Optional<WindowDecorViewModel> windowDecorViewModel) {
- super(context, taskOrganizer, displayId, callbacks, syncQueue, surfaceSession,
- iconProvider, windowDecorViewModel);
- }
-
- boolean isActive() {
- return mIsActive;
- }
-
- void activate(WindowContainerTransaction wct, boolean includingTopTask) {
- if (mIsActive) return;
- ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "activate: main stage includingTopTask=%b",
- includingTopTask);
-
- if (includingTopTask) {
- reparentTopTask(wct);
- }
-
- mIsActive = true;
- }
-
- void deactivate(WindowContainerTransaction wct) {
- deactivate(wct, false /* toTop */);
- }
-
- void deactivate(WindowContainerTransaction wct, boolean toTop) {
- if (!mIsActive) return;
- ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "deactivate: main stage toTop=%b rootTaskInfo=%s",
- toTop, mRootTaskInfo);
- mIsActive = false;
-
- if (mRootTaskInfo == null) return;
- final WindowContainerToken rootToken = mRootTaskInfo.token;
- wct.reparentTasks(
- rootToken,
- null /* newParent */,
- null /* windowingModes */,
- null /* activityTypes */,
- toTop);
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
deleted file mode 100644
index 27fd309..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.splitscreen;
-
-import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.view.SurfaceSession;
-import android.window.WindowContainerToken;
-import android.window.WindowContainerTransaction;
-
-import com.android.internal.protolog.ProtoLog;
-import com.android.launcher3.icons.IconProvider;
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.windowdecor.WindowDecorViewModel;
-
-import java.util.Optional;
-
-/**
- * Side stage for split-screen mode. Only tasks that are explicitly pinned to this stage show up
- * here. All other task are launch in the {@link MainStage}.
- *
- * @see StageCoordinator
- */
-class SideStage extends StageTaskListener {
- private static final String TAG = SideStage.class.getSimpleName();
-
- SideStage(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
- StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
- SurfaceSession surfaceSession, IconProvider iconProvider,
- Optional<WindowDecorViewModel> windowDecorViewModel) {
- super(context, taskOrganizer, displayId, callbacks, syncQueue, surfaceSession,
- iconProvider, windowDecorViewModel);
- }
-
- boolean removeAllTasks(WindowContainerTransaction wct, boolean toTop) {
- ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "remove all side stage tasks: childCount=%d toTop=%b",
- mChildrenTaskInfo.size(), toTop);
- if (mChildrenTaskInfo.size() == 0) return false;
- wct.reparentTasks(
- mRootTaskInfo.token,
- null /* newParent */,
- null /* windowingModes */,
- null /* activityTypes */,
- toTop);
- return true;
- }
-
- boolean removeTask(int taskId, WindowContainerToken newParent, WindowContainerTransaction wct) {
- final ActivityManager.RunningTaskInfo task = mChildrenTaskInfo.get(taskId);
- ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "remove side stage task: task=%d exists=%b", taskId,
- task != null);
- if (task == null) return false;
- wct.reparent(task.token, newParent, false /* onTop */);
- return true;
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
index a6233dc9..b36b1f8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
@@ -44,13 +44,13 @@
int STAGE_TYPE_UNDEFINED = -1;
/**
* The main stage type.
- * @see MainStage
+ * @see StageTaskListener
*/
int STAGE_TYPE_MAIN = 0;
/**
* The side stage type.
- * @see SideStage
+ * @see StageTaskListener
*/
int STAGE_TYPE_SIDE = 1;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 7e165af..793e2aa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -61,7 +61,6 @@
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
import android.view.WindowManager;
import android.widget.Toast;
import android.window.RemoteTransition;
@@ -897,7 +896,7 @@
private SurfaceControl reparentSplitTasksForAnimation(RemoteAnimationTarget[] apps,
SurfaceControl.Transaction t, String callsite) {
- final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
+ final SurfaceControl.Builder builder = new SurfaceControl.Builder()
.setContainerLayer()
.setName("RecentsAnimationSplitTasks")
.setHidden(false)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java
index cea995d..1e6fa28 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java
@@ -32,6 +32,7 @@
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__UNKNOWN_EXIT;
+import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASON_DRAG;
@@ -57,6 +58,7 @@
import com.android.internal.logging.InstanceId;
import com.android.internal.logging.InstanceIdSequence;
+import com.android.internal.protolog.ProtoLog;
import com.android.internal.util.FrameworkStatsLog;
import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition;
import com.android.wm.shell.splitscreen.SplitScreenController.ExitReason;
@@ -133,6 +135,11 @@
@SplitPosition int mainStagePosition, int mainStageUid,
@SplitPosition int sideStagePosition, int sideStageUid,
boolean isLandscape) {
+ if (hasStartedSession()) {
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logEnter: no-op, previous session has not ended");
+ return;
+ }
+
mLoggerSessionId = mIdSequence.newInstanceId();
int enterReason = getLoggerEnterReason(isLandscape);
updateMainStageState(getMainStagePositionFromSplitPosition(mainStagePosition, isLandscape),
@@ -140,6 +147,14 @@
updateSideStageState(getSideStagePositionFromSplitPosition(sideStagePosition, isLandscape),
sideStageUid);
updateSplitRatioState(splitRatio);
+
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logEnter: enterReason=%d splitRatio=%f "
+ + "mainStagePosition=%d mainStageUid=%d sideStagePosition=%d "
+ + "sideStageUid=%d isLandscape=%b mEnterSessionId=%d mLoggerSessionId=%d",
+ enterReason, splitRatio, mLastMainStagePosition, mLastMainStageUid,
+ mLastSideStagePosition, mLastSideStageUid, isLandscape,
+ mEnterSessionId != null ? mEnterSessionId.getId() : 0, mLoggerSessionId.getId());
+
FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__ENTER,
enterReason,
@@ -212,14 +227,25 @@
@SplitPosition int mainStagePosition, int mainStageUid,
@SplitPosition int sideStagePosition, int sideStageUid, boolean isLandscape) {
if (mLoggerSessionId == null) {
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logExit: no-op, mLoggerSessionId is null");
// Ignore changes until we've started logging the session
return;
}
if ((mainStagePosition != SPLIT_POSITION_UNDEFINED
&& sideStagePosition != SPLIT_POSITION_UNDEFINED)
|| (mainStageUid != 0 && sideStageUid != 0)) {
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN,
+ "logExit: no-op, only main or side stage should be set, not both/none");
throw new IllegalArgumentException("Only main or side stage should be set");
}
+
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logExit: exitReason=%d mainStagePosition=%d"
+ + " mainStageUid=%d sideStagePosition=%d sideStageUid=%d isLandscape=%b"
+ + " mLoggerSessionId=%d", getLoggerExitReason(exitReason),
+ getMainStagePositionFromSplitPosition(mainStagePosition, isLandscape), mainStageUid,
+ getSideStagePositionFromSplitPosition(sideStagePosition, isLandscape), sideStageUid,
+ isLandscape, mLoggerSessionId.getId());
+
FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__EXIT,
0 /* enterReason */,
@@ -304,18 +330,25 @@
*/
public void logResize(float splitRatio) {
if (mLoggerSessionId == null) {
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logResize: no-op, mLoggerSessionId is null");
// Ignore changes until we've started logging the session
return;
}
if (splitRatio <= 0f || splitRatio >= 1f) {
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN,
+ "logResize: no-op, splitRatio indicates that user is dismissing, not resizing");
// Don't bother reporting resizes that end up dismissing the split, that will be logged
// via the exit event
return;
}
if (!updateSplitRatioState(splitRatio)) {
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logResize: no-op, split ratio was not changed");
// Ignore if there are no user perceived changes
return;
}
+
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logResize: splitRatio=%f mLoggerSessionId=%d",
+ mLastSplitRatio, mLoggerSessionId.getId());
FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__RESIZE,
0 /* enterReason */,
@@ -335,6 +368,7 @@
public void logSwap(@SplitPosition int mainStagePosition, int mainStageUid,
@SplitPosition int sideStagePosition, int sideStageUid, boolean isLandscape) {
if (mLoggerSessionId == null) {
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logSwap: no-op, mLoggerSessionId is null");
// Ignore changes until we've started logging the session
return;
}
@@ -343,6 +377,11 @@
mainStageUid);
updateSideStageState(getSideStagePositionFromSplitPosition(sideStagePosition, isLandscape),
sideStageUid);
+
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logSwap: mainStagePosition=%d mainStageUid=%d "
+ + "sideStagePosition=%d sideStageUid=%d mLoggerSessionId=%d",
+ mLastMainStagePosition, mLastMainStageUid, mLastSideStagePosition,
+ mLastSideStageUid, mLoggerSessionId.getId());
FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__SWAP,
0 /* enterReason */,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 8921ceb..dad0d4e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -34,6 +34,7 @@
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
+import static com.android.wm.shell.Flags.enableFlexibleSplit;
import static com.android.wm.shell.common.split.SplitLayout.PARALLAX_ALIGN_CENTER;
import static com.android.wm.shell.common.split.SplitScreenUtils.reverseSplitPosition;
import static com.android.wm.shell.common.split.SplitScreenUtils.splitFailureMessage;
@@ -103,7 +104,6 @@
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
import android.view.WindowManager;
import android.widget.Toast;
import android.window.DisplayAreaInfo;
@@ -154,14 +154,12 @@
import java.util.concurrent.Executor;
/**
- * Coordinates the staging (visibility, sizing, ...) of the split-screen {@link MainStage} and
- * {@link SideStage} stages.
+ * Coordinates the staging (visibility, sizing, ...) of the split-screen stages.
* Some high-level rules:
- * - The {@link StageCoordinator} is only considered active if the {@link SideStage} contains at
+ * - The {@link StageCoordinator} is only considered active if the other stages contain at
* least one child task.
- * - The {@link MainStage} should only have children if the coordinator is active.
- * - The {@link SplitLayout} divider is only visible if both the {@link MainStage}
- * and {@link SideStage} are visible.
+ * - The {@link SplitLayout} divider is only visible if multiple {@link StageTaskListener}s are
+ * visible
* - Both stages are put under a single-top root task.
* This rules are mostly implemented in {@link #onStageVisibilityChanged(StageListenerImpl)} and
* {@link #onStageHasChildrenChanged(StageListenerImpl).}
@@ -172,11 +170,9 @@
private static final String TAG = StageCoordinator.class.getSimpleName();
- private final SurfaceSession mSurfaceSession = new SurfaceSession();
-
- private final MainStage mMainStage;
+ private final StageTaskListener mMainStage;
private final StageListenerImpl mMainStageListener = new StageListenerImpl();
- private final SideStage mSideStage;
+ private final StageTaskListener mSideStage;
private final StageListenerImpl mSideStageListener = new StageListenerImpl();
@SplitPosition
private int mSideStagePosition = SPLIT_POSITION_BOTTOM_OR_RIGHT;
@@ -329,22 +325,20 @@
taskOrganizer.createRootTask(displayId, WINDOWING_MODE_FULLSCREEN, this /* listener */);
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "Creating main/side root task");
- mMainStage = new MainStage(
+ mMainStage = new StageTaskListener(
mContext,
mTaskOrganizer,
mDisplayId,
mMainStageListener,
mSyncQueue,
- mSurfaceSession,
iconProvider,
mWindowDecorViewModel);
- mSideStage = new SideStage(
+ mSideStage = new StageTaskListener(
mContext,
mTaskOrganizer,
mDisplayId,
mSideStageListener,
mSyncQueue,
- mSurfaceSession,
iconProvider,
mWindowDecorViewModel);
mDisplayController = displayController;
@@ -367,8 +361,9 @@
@VisibleForTesting
StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
- ShellTaskOrganizer taskOrganizer, MainStage mainStage, SideStage sideStage,
- DisplayController displayController, DisplayImeController displayImeController,
+ ShellTaskOrganizer taskOrganizer, StageTaskListener mainStage,
+ StageTaskListener sideStage, DisplayController displayController,
+ DisplayImeController displayImeController,
DisplayInsetsController displayInsetsController, SplitLayout splitLayout,
Transitions transitions, TransactionPool transactionPool, ShellExecutor mainExecutor,
Handler mainHandler, Optional<RecentTasksController> recentTasks,
@@ -420,10 +415,23 @@
return mSideStageListener.mVisible && mMainStageListener.mVisible;
}
+ private void activateSplit(WindowContainerTransaction wct, boolean includingTopTask) {
+ mMainStage.activate(wct, includingTopTask);
+ }
+
public boolean isSplitActive() {
return mMainStage.isActive();
}
+ /**
+ * Deactivates main stage by removing the stage from the top level split root (usually when a
+ * task underneath gets removed from the stage root).
+ * @param reparentToTop whether we want to put the stage root back on top
+ */
+ private void deactivateSplit(WindowContainerTransaction wct, boolean reparentToTop) {
+ mMainStage.deactivate(wct, reparentToTop);
+ }
+
/** @return whether this transition-request has the launch-adjacent flag. */
public boolean requestHasLaunchAdjacentFlag(TransitionRequestInfo request) {
final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask();
@@ -496,12 +504,12 @@
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "removeFromSideStage: task=%d", taskId);
final WindowContainerTransaction wct = new WindowContainerTransaction();
- /**
- * {@link MainStage} will be deactivated in {@link #onStageHasChildrenChanged} if the
- * {@link SideStage} no longer has children.
- */
+
+ // MainStage will be deactivated in onStageHasChildrenChanged() if the other stages
+ // no longer have children.
+
final boolean result = mSideStage.removeTask(taskId,
- mMainStage.isActive() ? mMainStage.mRootTaskInfo.token : null,
+ isSplitActive() ? mMainStage.mRootTaskInfo.token : null,
wct);
mTaskOrganizer.applyTransaction(wct);
return result;
@@ -618,7 +626,7 @@
}
// If split screen is not activated, we're expecting to open a pair of apps to split.
- final int extraTransitType = mMainStage.isActive()
+ final int extraTransitType = isSplitActive()
? TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE : TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
prepareEnterSplitScreen(wct, null /* taskInfo */, position, !mIsDropEntering);
@@ -661,7 +669,7 @@
}
// If split screen is not activated, we're expecting to open a pair of apps to split.
- final int extraTransitType = mMainStage.isActive()
+ final int extraTransitType = isSplitActive()
? TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE : TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
prepareEnterSplitScreen(wct, null /* taskInfo */, position, !mIsDropEntering);
@@ -793,10 +801,10 @@
private void startWithTask(WindowContainerTransaction wct, int mainTaskId,
@Nullable Bundle mainOptions, @PersistentSnapPosition int snapPosition,
@Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
- if (!mMainStage.isActive()) {
+ if (!isSplitActive()) {
// Build a request WCT that will launch both apps such that task 0 is on the main stage
// while task 1 is on the side stage.
- mMainStage.activate(wct, false /* reparent */);
+ activateSplit(wct, false /* reparentToTop */);
}
mSplitLayout.setDivideRatio(snapPosition);
updateWindowBounds(mSplitLayout, wct);
@@ -860,10 +868,10 @@
return;
}
- if (!mMainStage.isActive()) {
+ if (!isSplitActive()) {
// Build a request WCT that will launch both apps such that task 0 is on the main stage
// while task 1 is on the side stage.
- mMainStage.activate(wct, false /* reparent */);
+ activateSplit(wct, false /* reparentToTop */);
}
setSideStagePosition(splitPosition, wct);
@@ -1110,7 +1118,7 @@
*/
void onKeyguardStateChanged(boolean active, boolean occludingTaskRunning) {
mKeyguardActive = active;
- if (!mMainStage.isActive()) {
+ if (!isSplitActive()) {
return;
}
ProtoLog.d(WM_SHELL_SPLIT_SCREEN,
@@ -1154,7 +1162,7 @@
* will do a no-op.
*/
void dismissSplitKeepingLastActiveStage(@ExitReason int reason) {
- if (!mMainStage.isActive() || mLastActiveStage == STAGE_TYPE_UNDEFINED) {
+ if (!isSplitActive() || mLastActiveStage == STAGE_TYPE_UNDEFINED) {
// no-op
return;
}
@@ -1177,8 +1185,8 @@
private void exitSplitScreen(@Nullable StageTaskListener childrenToTop,
@ExitReason int exitReason) {
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "exitSplitScreen: mainStageToTop=%b reason=%s active=%b",
- childrenToTop == mMainStage, exitReasonToString(exitReason), mMainStage.isActive());
- if (!mMainStage.isActive()) return;
+ childrenToTop == mMainStage, exitReasonToString(exitReason), isSplitActive());
+ if (!isSplitActive()) return;
final WindowContainerTransaction wct = new WindowContainerTransaction();
applyExitSplitScreen(childrenToTop, wct, exitReason);
@@ -1188,7 +1196,7 @@
WindowContainerTransaction wct, @ExitReason int exitReason) {
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "applyExitSplitScreen: reason=%s",
exitReasonToString(exitReason));
- if (!mMainStage.isActive() || mIsExiting) return;
+ if (!isSplitActive() || mIsExiting) return;
onSplitScreenExit();
clearSplitPairedInRecents(exitReason);
@@ -1200,7 +1208,7 @@
mSplitLayout.getInvisibleBounds(mTempRect1);
if (childrenToTop == null || childrenToTop.getTopVisibleChildTaskId() == INVALID_TASK_ID) {
mSideStage.removeAllTasks(wct, false /* toTop */);
- mMainStage.deactivate(wct, false /* toTop */);
+ deactivateSplit(wct, false /* reparentToTop */);
wct.reorder(mRootTaskInfo.token, false /* onTop */);
setRootForceTranslucent(true, wct);
wct.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1);
@@ -1229,7 +1237,7 @@
childrenToTop.fadeOutDecor(() -> {
WindowContainerTransaction finishedWCT = new WindowContainerTransaction();
mIsExiting = false;
- mMainStage.deactivate(finishedWCT, childrenToTop == mMainStage /* toTop */);
+ deactivateSplit(finishedWCT, childrenToTop == mMainStage /* reparentToTop */);
mSideStage.removeAllTasks(finishedWCT, childrenToTop == mSideStage /* toTop */);
finishedWCT.reorder(mRootTaskInfo.token, false /* toTop */);
setRootForceTranslucent(true, finishedWCT);
@@ -1252,7 +1260,7 @@
}
void dismissSplitScreen(int toTopTaskId, @ExitReason int exitReason) {
- if (!mMainStage.isActive()) return;
+ if (!isSplitActive()) return;
final int stage = getStageOfTask(toTopTaskId);
final WindowContainerTransaction wct = new WindowContainerTransaction();
prepareExitSplitScreen(stage, wct);
@@ -1362,10 +1370,10 @@
*/
void prepareExitSplitScreen(@StageType int stageToTop,
@NonNull WindowContainerTransaction wct) {
- if (!mMainStage.isActive()) return;
+ if (!isSplitActive()) return;
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "prepareExitSplitScreen: stageToTop=%d", stageToTop);
mSideStage.removeAllTasks(wct, stageToTop == STAGE_TYPE_SIDE);
- mMainStage.deactivate(wct, stageToTop == STAGE_TYPE_MAIN);
+ deactivateSplit(wct, stageToTop == STAGE_TYPE_MAIN);
}
private void prepareEnterSplitScreen(WindowContainerTransaction wct) {
@@ -1430,7 +1438,7 @@
setSideStagePosition(startPosition, wct);
mSideStage.addTask(taskInfo, wct);
}
- mMainStage.activate(wct, true /* includingTopTask */);
+ activateSplit(wct, true /* reparentToTop */);
prepareSplitLayout(wct, resizeAnim);
}
@@ -1471,12 +1479,11 @@
mSkipEvictingMainStageChildren = false;
mSplitRequest = null;
updateRecentTasksSplitPair();
- if (!mLogger.hasStartedSession()) {
- mLogger.logEnter(mSplitLayout.getDividerPositionAsFraction(),
- getMainStagePosition(), mMainStage.getTopChildTaskUid(),
- getSideStagePosition(), mSideStage.getTopChildTaskUid(),
- mSplitLayout.isLeftRightSplit());
- }
+
+ mLogger.logEnter(mSplitLayout.getDividerPositionAsFraction(),
+ getMainStagePosition(), mMainStage.getTopChildTaskUid(),
+ getSideStagePosition(), mSideStage.getTopChildTaskUid(),
+ mSplitLayout.isLeftRightSplit());
}
void getStageBounds(Rect outTopOrLeftBounds, Rect outBottomOrRightBounds) {
@@ -1662,7 +1669,7 @@
mRootTaskInfo = taskInfo;
if (mSplitLayout != null
&& mSplitLayout.updateConfiguration(mRootTaskInfo.configuration)
- && mMainStage.isActive()) {
+ && isSplitActive()) {
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onTaskInfoChanged: task=%d updating",
taskInfo.taskId);
// Clear the divider remote animating flag as the divider will be re-rendered to apply
@@ -1916,7 +1923,7 @@
stageListener == mMainStageListener);
final boolean hasChildren = stageListener.mHasChildren;
final boolean isSideStage = stageListener == mSideStageListener;
- if (!hasChildren && !mIsExiting && mMainStage.isActive()) {
+ if (!hasChildren && !mIsExiting && isSplitActive()) {
if (isSideStage && mMainStageListener.mVisible) {
// Exit to main stage if side stage no longer has children.
mSplitLayout.flingDividerToDismiss(
@@ -1931,7 +1938,7 @@
// Dismiss split screen in the background once any sides of the split become empty.
exitSplitScreen(null /* childrenToTop */, EXIT_REASON_APP_FINISHED);
}
- } else if (isSideStage && hasChildren && !mMainStage.isActive()) {
+ } else if (isSideStage && hasChildren && !isSplitActive()) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
prepareEnterSplitScreen(wct);
@@ -1952,15 +1959,13 @@
clearRequestIfPresented();
updateRecentTasksSplitPair();
- if (!mLogger.hasStartedSession()) {
- if (!mLogger.hasValidEnterSessionId()) {
- mLogger.enterRequested(null /*enterSessionId*/, ENTER_REASON_MULTI_INSTANCE);
- }
- mLogger.logEnter(mSplitLayout.getDividerPositionAsFraction(),
- getMainStagePosition(), mMainStage.getTopChildTaskUid(),
- getSideStagePosition(), mSideStage.getTopChildTaskUid(),
- mSplitLayout.isLeftRightSplit());
+ if (!mLogger.hasStartedSession() && !mLogger.hasValidEnterSessionId()) {
+ mLogger.enterRequested(null /*enterSessionId*/, ENTER_REASON_MULTI_INSTANCE);
}
+ mLogger.logEnter(mSplitLayout.getDividerPositionAsFraction(),
+ getMainStagePosition(), mMainStage.getTopChildTaskUid(),
+ getSideStagePosition(), mSideStage.getTopChildTaskUid(),
+ mSplitLayout.isLeftRightSplit());
}
}
@@ -2146,7 +2151,7 @@
private void onDisplayChange(int displayId, int fromRotation, int toRotation,
@Nullable DisplayAreaInfo newDisplayAreaInfo, WindowContainerTransaction wct) {
- if (displayId != DEFAULT_DISPLAY || !mMainStage.isActive()) {
+ if (displayId != DEFAULT_DISPLAY || !isSplitActive()) {
return;
}
@@ -2441,7 +2446,7 @@
// Not entering or exiting, so just do some house-keeping and validation.
// If we're not in split-mode, just abort so something else can handle it.
- if (!mMainStage.isActive()) return false;
+ if (!isSplitActive()) return false;
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "startAnimation: transition=%d", info.getDebugId());
mSplitLayout.setFreezeDividerWindow(false);
@@ -2683,7 +2688,7 @@
public void onTransitionAnimationComplete() {
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onTransitionAnimationComplete");
// If still playing, let it finish.
- if (!mMainStage.isActive() && !mIsExiting) {
+ if (!isSplitActive() && !mIsExiting) {
// Update divider state after animation so that it is still around and positioned
// properly for the animation itself.
mSplitLayout.release();
@@ -3147,7 +3152,7 @@
+ (mSplitLayout != null ? mSplitLayout.isLeftRightSplit() : "null"));
pw.println(innerPrefix + "MainStage");
pw.println(childPrefix + "stagePosition=" + splitPositionToString(getMainStagePosition()));
- pw.println(childPrefix + "isActive=" + mMainStage.isActive());
+ pw.println(childPrefix + "isActive=" + isSplitActive());
mMainStage.dump(pw, childPrefix);
pw.println(innerPrefix + "MainStageListener");
mMainStageListener.dump(pw, childPrefix);
@@ -3267,7 +3272,7 @@
@Override
public void onNoLongerSupportMultiWindow(ActivityManager.RunningTaskInfo taskInfo) {
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onNoLongerSupportMultiWindow: task=%s", taskInfo);
- if (mMainStage.isActive()) {
+ if (isSplitActive()) {
final boolean isMainStage = mMainStageListener == this;
// If visible, we preserve the app and keep it running. If an app becomes
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index 99f3832..d64c0a2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -39,7 +39,6 @@
import android.util.SparseArray;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
@@ -72,6 +71,10 @@
public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
private static final String TAG = StageTaskListener.class.getSimpleName();
+ // No current way to enforce this but if enableFlexibleSplit() is enabled, then only 1 of the
+ // stages should have this be set/being used
+ private boolean mIsActive;
+
/** Callback interface for listening to changes in a split-screen stage. */
public interface StageListenerCallbacks {
void onRootTaskAppeared();
@@ -89,7 +92,6 @@
private final Context mContext;
private final StageListenerCallbacks mCallbacks;
- private final SurfaceSession mSurfaceSession;
private final SyncTransactionQueue mSyncQueue;
private final IconProvider mIconProvider;
private final Optional<WindowDecorViewModel> mWindowDecorViewModel;
@@ -104,12 +106,11 @@
StageTaskListener(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
- SurfaceSession surfaceSession, IconProvider iconProvider,
+ IconProvider iconProvider,
Optional<WindowDecorViewModel> windowDecorViewModel) {
mContext = context;
mCallbacks = callbacks;
mSyncQueue = syncQueue;
- mSurfaceSession = surfaceSession;
mIconProvider = iconProvider;
mWindowDecorViewModel = windowDecorViewModel;
taskOrganizer.createRootTask(displayId, WINDOWING_MODE_MULTI_WINDOW, this);
@@ -199,12 +200,11 @@
mRootTaskInfo = taskInfo;
mSplitDecorManager = new SplitDecorManager(
mRootTaskInfo.configuration,
- mIconProvider,
- mSurfaceSession);
+ mIconProvider);
mCallbacks.onRootTaskAppeared();
sendStatusChanged();
mSyncQueue.runInSync(t -> mDimLayer =
- SurfaceUtils.makeDimLayer(t, mRootLeash, "Dim layer", mSurfaceSession));
+ SurfaceUtils.makeDimLayer(t, mRootLeash, "Dim layer"));
} else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) {
final int taskId = taskInfo.taskId;
mChildrenLeashes.put(taskId, leash);
@@ -475,6 +475,68 @@
});
}
+ // ---------
+ // Previously only used in MainStage
+ boolean isActive() {
+ return mIsActive;
+ }
+
+ void activate(WindowContainerTransaction wct, boolean includingTopTask) {
+ if (mIsActive) return;
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "activate: includingTopTask=%b",
+ includingTopTask);
+
+ if (includingTopTask) {
+ reparentTopTask(wct);
+ }
+
+ mIsActive = true;
+ }
+
+ void deactivate(WindowContainerTransaction wct) {
+ deactivate(wct, false /* toTop */);
+ }
+
+ void deactivate(WindowContainerTransaction wct, boolean toTop) {
+ if (!mIsActive) return;
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "deactivate: toTop=%b rootTaskInfo=%s",
+ toTop, mRootTaskInfo);
+ mIsActive = false;
+
+ if (mRootTaskInfo == null) return;
+ final WindowContainerToken rootToken = mRootTaskInfo.token;
+ wct.reparentTasks(
+ rootToken,
+ null /* newParent */,
+ null /* windowingModes */,
+ null /* activityTypes */,
+ toTop);
+ }
+
+ // --------
+ // Previously only used in SideStage
+ boolean removeAllTasks(WindowContainerTransaction wct, boolean toTop) {
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "remove all side stage tasks: childCount=%d toTop=%b",
+ mChildrenTaskInfo.size(), toTop);
+ if (mChildrenTaskInfo.size() == 0) return false;
+ wct.reparentTasks(
+ mRootTaskInfo.token,
+ null /* newParent */,
+ null /* windowingModes */,
+ null /* activityTypes */,
+ toTop);
+ return true;
+ }
+
+ boolean removeTask(int taskId, WindowContainerToken newParent, WindowContainerTransaction wct) {
+ final ActivityManager.RunningTaskInfo task = mChildrenTaskInfo.get(taskId);
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "remove side stage task: task=%d exists=%b", taskId,
+ task != null);
+ if (task == null) return false;
+ wct.reparent(task.token, newParent, false /* onTop */);
+ return true;
+ }
+
private void sendStatusChanged() {
mCallbacks.onStatusChanged(mRootTaskInfo.isVisible, mChildrenTaskInfo.size() > 0);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index fac3592..2e9b53e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -33,7 +33,6 @@
import android.util.SparseArray;
import android.view.IWindow;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
import android.view.WindowManager;
import android.view.WindowlessWindowManager;
import android.window.SplashScreenView;
@@ -204,7 +203,7 @@
@Override
protected SurfaceControl getParentSurface(IWindow window,
WindowManager.LayoutParams attrs) {
- final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
+ final SurfaceControl.Builder builder = new SurfaceControl.Builder()
.setContainerLayer()
.setName("Windowless window")
.setHidden(false)
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 0259701..e74342e 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
@@ -604,7 +604,6 @@
});
}
mTaskViewBase.onTaskVanished(taskInfo);
- mTaskOrganizer.setInterceptBackPressedOnTaskRoot(taskInfo.token, false);
}
}
@@ -718,6 +717,9 @@
mTaskViewBase.setResizeBgColor(startTransaction, backgroundColor);
}
+ // After the embedded task has appeared, set it to non-trimmable. This is important
+ // to prevent recents from trimming and removing the embedded task.
+ wct.setTaskTrimmableFromRecents(taskInfo.token, false /* isTrimmableFromRecents */);
mTaskViewBase.onTaskAppeared(mTaskInfo, mTaskLeash);
if (mListener != null) {
final int taskId = mTaskInfo.taskId;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index 9b0fb20..ff4b981 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -18,8 +18,8 @@
import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
import static android.app.ActivityOptions.ANIM_CUSTOM;
-import static android.app.ActivityOptions.ANIM_FROM_STYLE;
import static android.app.ActivityOptions.ANIM_NONE;
+import static android.app.ActivityOptions.ANIM_FROM_STYLE;
import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS;
import static android.app.ActivityOptions.ANIM_SCALE_UP;
import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
@@ -92,7 +92,6 @@
import android.util.ArrayMap;
import android.view.Choreographer;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
@@ -134,8 +133,6 @@
private final TransitionAnimation mTransitionAnimation;
private final DevicePolicyManager mDevicePolicyManager;
- private final SurfaceSession mSurfaceSession = new SurfaceSession();
-
/** Keeps track of the currently-running animations associated with each transition. */
private final ArrayMap<IBinder, ArrayList<Animator>> mAnimations = new ArrayMap<>();
@@ -473,7 +470,7 @@
change.getLeash(),
startTransaction);
} else if (isOnlyTranslucent && TransitionUtil.isOpeningType(info.getType())
- && TransitionUtil.isClosingType(mode)) {
+ && TransitionUtil.isClosingType(mode)) {
// If there is a closing translucent task in an OPENING transition, we will
// actually select a CLOSING animation, so move the closing task into
// the animating part of the z-order.
@@ -705,7 +702,7 @@
TransitionInfo.Change change, TransitionInfo info, int animHint,
ArrayList<Animator> animations, Runnable onAnimFinish) {
final int rootIdx = TransitionUtil.rootIndexFor(change, info);
- final ScreenRotationAnimation anim = new ScreenRotationAnimation(mContext, mSurfaceSession,
+ final ScreenRotationAnimation anim = new ScreenRotationAnimation(mContext,
mTransactionPool, startTransaction, change, info.getRoot(rootIdx).getLeash(),
animHint);
// The rotation animation may consist of 3 animations: fade-out screenshot, fade-in real
@@ -767,12 +764,12 @@
a = mTransitionAnimation.loadKeyguardExitAnimation(flags,
(changeFlags & FLAG_SHOW_WALLPAPER) != 0);
} else if (type == TRANSIT_KEYGUARD_UNOCCLUDE) {
- a = mTransitionAnimation.loadKeyguardUnoccludeAnimation(options.getUserId());
+ a = mTransitionAnimation.loadKeyguardUnoccludeAnimation();
} else if ((changeFlags & FLAG_IS_VOICE_INTERACTION) != 0) {
if (isOpeningType) {
- a = mTransitionAnimation.loadVoiceActivityOpenAnimation(enter, options.getUserId());
+ a = mTransitionAnimation.loadVoiceActivityOpenAnimation(enter);
} else {
- a = mTransitionAnimation.loadVoiceActivityExitAnimation(enter, options.getUserId());
+ a = mTransitionAnimation.loadVoiceActivityExitAnimation(enter);
}
} else if (changeMode == TRANSIT_CHANGE) {
// In the absence of a specific adapter, we just want to keep everything stationary.
@@ -783,9 +780,9 @@
} else if (overrideType == ANIM_CUSTOM
&& (!isTask || options.getOverrideTaskTransition())) {
a = mTransitionAnimation.loadAnimationRes(options.getPackageName(), enter
- ? options.getEnterResId() : options.getExitResId(), options.getUserId());
+ ? options.getEnterResId() : options.getExitResId());
} else if (overrideType == ANIM_OPEN_CROSS_PROFILE_APPS && enter) {
- a = mTransitionAnimation.loadCrossProfileAppEnterAnimation(options.getUserId());
+ a = mTransitionAnimation.loadCrossProfileAppEnterAnimation();
} else if (overrideType == ANIM_CLIP_REVEAL) {
a = mTransitionAnimation.createClipRevealAnimationLocked(type, wallpaperTransit, enter,
endBounds, endBounds, options.getTransitionBounds());
@@ -905,9 +902,9 @@
final Rect bounds = change.getEndAbsBounds();
// Show the right drawable depending on the user we're transitioning to.
final Drawable thumbnailDrawable = change.hasFlags(FLAG_CROSS_PROFILE_OWNER_THUMBNAIL)
- ? mContext.getDrawable(R.drawable.ic_account_circle)
- : change.hasFlags(FLAG_CROSS_PROFILE_WORK_THUMBNAIL)
- ? mEnterpriseThumbnailDrawable : null;
+ ? mContext.getDrawable(R.drawable.ic_account_circle)
+ : change.hasFlags(FLAG_CROSS_PROFILE_WORK_THUMBNAIL)
+ ? mEnterpriseThumbnailDrawable : null;
if (thumbnailDrawable == null) {
return;
}
@@ -918,7 +915,7 @@
}
final SurfaceControl.Transaction transaction = mTransactionPool.acquire();
- final WindowThumbnail wt = WindowThumbnail.createAndAttach(mSurfaceSession,
+ final WindowThumbnail wt = WindowThumbnail.createAndAttach(
change.getLeash(), thumbnail, transaction);
final Animation a =
mTransitionAnimation.createCrossProfileAppsThumbnailAnimationLocked(bounds);
@@ -943,7 +940,7 @@
@NonNull Runnable finishCallback, TransitionInfo.Change change,
TransitionInfo.AnimationOptions options, float cornerRadius) {
final SurfaceControl.Transaction transaction = mTransactionPool.acquire();
- final WindowThumbnail wt = WindowThumbnail.createAndAttach(mSurfaceSession,
+ final WindowThumbnail wt = WindowThumbnail.createAndAttach(
change.getLeash(), options.getThumbnail(), transaction);
final Rect bounds = change.getEndAbsBounds();
final int orientation = mContext.getResources().getConfiguration().orientation;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
index 9b27e41..c385f9a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
@@ -30,6 +30,7 @@
import android.view.SurfaceControl;
import android.window.TransitionInfo;
+import com.android.window.flags.Flags;
import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SingleInstanceRemoteListener;
@@ -71,9 +72,21 @@
final int mode = change.getMode();
final boolean isBackGesture = change.hasFlags(FLAG_BACK_GESTURE_ANIMATED);
- if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME
- && (TransitionUtil.isOpenOrCloseMode(mode) || isBackGesture)) {
- notifyHomeVisibilityChanged(TransitionUtil.isOpeningType(mode) || isBackGesture);
+ if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME) {
+ if (Flags.migratePredictiveBackTransition()) {
+ final boolean gestureToHomeTransition = isBackGesture
+ && TransitionUtil.isClosingType(info.getType());
+ if (gestureToHomeTransition
+ || (!isBackGesture && TransitionUtil.isOpenOrCloseMode(mode))) {
+ notifyHomeVisibilityChanged(gestureToHomeTransition
+ || TransitionUtil.isOpeningType(mode));
+ }
+ } else {
+ if (TransitionUtil.isOpenOrCloseMode(mode) || isBackGesture) {
+ notifyHomeVisibilityChanged(TransitionUtil.isOpeningType(mode)
+ || isBackGesture);
+ }
+ }
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
index 0bf9d36..5802e2c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
@@ -38,7 +38,6 @@
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
-import android.view.SurfaceSession;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.window.ScreenCapture;
@@ -112,7 +111,7 @@
/** Intensity of light/whiteness of the layout after rotation occurs. */
private float mEndLuma;
- ScreenRotationAnimation(Context context, SurfaceSession session, TransactionPool pool,
+ ScreenRotationAnimation(Context context, TransactionPool pool,
Transaction t, TransitionInfo.Change change, SurfaceControl rootLeash, int animHint) {
mContext = context;
mTransactionPool = pool;
@@ -126,7 +125,7 @@
mStartRotation = change.getStartRotation();
mEndRotation = change.getEndRotation();
- mAnimLeash = new SurfaceControl.Builder(session)
+ mAnimLeash = new SurfaceControl.Builder()
.setParent(rootLeash)
.setEffectLayer()
.setCallsite("ShellRotationAnimation")
@@ -153,7 +152,7 @@
return;
}
- mScreenshotLayer = new SurfaceControl.Builder(session)
+ mScreenshotLayer = new SurfaceControl.Builder()
.setParent(mAnimLeash)
.setBLASTLayer()
.setSecure(screenshotBuffer.containsSecureLayers())
@@ -178,7 +177,7 @@
t.setCrop(mSurfaceControl, new Rect(0, 0, mEndWidth, mEndHeight));
if (!isCustomRotate()) {
- mBackColorSurface = new SurfaceControl.Builder(session)
+ mBackColorSurface = new SurfaceControl.Builder()
.setParent(rootLeash)
.setColorLayer()
.setOpaque(true)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/WindowThumbnail.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/WindowThumbnail.java
index 2c668ed..341f2bc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/WindowThumbnail.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/WindowThumbnail.java
@@ -21,7 +21,6 @@
import android.graphics.PixelFormat;
import android.hardware.HardwareBuffer;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
/**
* Represents a surface that is displayed over a transition surface.
@@ -33,10 +32,10 @@
private WindowThumbnail() {}
/** Create a thumbnail surface and attach it over a parent surface. */
- static WindowThumbnail createAndAttach(SurfaceSession surfaceSession, SurfaceControl parent,
+ static WindowThumbnail createAndAttach(SurfaceControl parent,
HardwareBuffer thumbnailHeader, SurfaceControl.Transaction t) {
WindowThumbnail windowThumbnail = new WindowThumbnail();
- windowThumbnail.mSurfaceControl = new SurfaceControl.Builder(surfaceSession)
+ windowThumbnail.mSurfaceControl = new SurfaceControl.Builder()
.setParent(parent)
.setName("WindowThumanil : " + parent.toString())
.setCallsite("WindowThumanil")
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 c88c1e2..7919068 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
@@ -90,6 +90,7 @@
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser;
+import com.android.wm.shell.apptoweb.AssistContentRequester;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayInsetsController;
@@ -182,6 +183,7 @@
private final Region mExclusionRegion = Region.obtain();
private boolean mInImmersiveMode;
private final String mSysUIPackageName;
+ private final AssistContentRequester mAssistContentRequester;
private final DisplayChangeController.OnDisplayChangingListener mOnDisplayChangingListener;
private final ISystemGestureExclusionListener mGestureExclusionListener =
@@ -217,6 +219,7 @@
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
InteractionJankMonitor interactionJankMonitor,
AppToWebGenericLinksParser genericLinksParser,
+ AssistContentRequester assistContentRequester,
MultiInstanceHelper multiInstanceHelper,
Optional<DesktopTasksLimiter> desktopTasksLimiter,
Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler
@@ -238,6 +241,7 @@
transitions,
desktopTasksController,
genericLinksParser,
+ assistContentRequester,
multiInstanceHelper,
new DesktopModeWindowDecoration.Factory(),
new InputMonitorFactory(),
@@ -267,6 +271,7 @@
Transitions transitions,
Optional<DesktopTasksController> desktopTasksController,
AppToWebGenericLinksParser genericLinksParser,
+ AssistContentRequester assistContentRequester,
MultiInstanceHelper multiInstanceHelper,
DesktopModeWindowDecoration.Factory desktopModeWindowDecorFactory,
InputMonitorFactory inputMonitorFactory,
@@ -304,6 +309,7 @@
mInteractionJankMonitor = interactionJankMonitor;
mDesktopTasksLimiter = desktopTasksLimiter;
mActivityOrientationChangeHandler = activityOrientationChangeHandler;
+ mAssistContentRequester = assistContentRequester;
mOnDisplayChangingListener = (displayId, fromRotation, toRotation, displayAreaInfo, t) -> {
DesktopModeWindowDecoration decoration;
RunningTaskInfo taskInfo;
@@ -626,7 +632,7 @@
} else if (id == R.id.caption_handle || id == R.id.open_menu_button) {
if (!decoration.isHandleMenuActive()) {
moveTaskToFront(decoration.mTaskInfo);
- decoration.createHandleMenu(mSplitScreenController);
+ decoration.createHandleMenu();
}
} else if (id == R.id.maximize_window) {
// TODO(b/346441962): move click detection logic into the decor's
@@ -1270,6 +1276,7 @@
mSyncQueue,
mRootTaskDisplayAreaOrganizer,
mGenericLinksParser,
+ mAssistContentRequester,
mMultiInstanceHelper);
mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 81251b8..142be91 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -38,6 +38,7 @@
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.WindowConfiguration.WindowingMode;
+import android.app.assist.AssistContent;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -75,6 +76,8 @@
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser;
+import com.android.wm.shell.apptoweb.AppToWebUtils;
+import com.android.wm.shell.apptoweb.AssistContentRequester;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.MultiInstanceHelper;
@@ -114,6 +117,7 @@
private final Choreographer mChoreographer;
private final SyncTransactionQueue mSyncQueue;
private final SplitScreenController mSplitScreenController;
+ private final WindowManagerWrapper mWindowManagerWrapper;
private WindowDecorationViewHolder mWindowDecorViewHolder;
private View.OnClickListener mOnCaptionButtonClickListener;
@@ -149,6 +153,7 @@
private CharSequence mAppName;
private CapturedLink mCapturedLink;
private Uri mGenericLink;
+ private Uri mWebUri;
private Consumer<Uri> mOpenInBrowserClickListener;
private ExclusionRegionListener mExclusionRegionListener;
@@ -157,6 +162,7 @@
private final MaximizeMenuFactory mMaximizeMenuFactory;
private final HandleMenuFactory mHandleMenuFactory;
private final AppToWebGenericLinksParser mGenericLinksParser;
+ private final AssistContentRequester mAssistContentRequester;
// Hover state for the maximize menu and button. The menu will remain open as long as either of
// these is true. See {@link #onMaximizeHoverStateChanged()}.
@@ -183,14 +189,16 @@
SyncTransactionQueue syncQueue,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
AppToWebGenericLinksParser genericLinksParser,
+ AssistContentRequester assistContentRequester,
MultiInstanceHelper multiInstanceHelper) {
this (context, userContext, displayController, splitScreenController, taskOrganizer,
taskInfo, taskSurface, handler, bgExecutor, choreographer, syncQueue,
- rootTaskDisplayAreaOrganizer, genericLinksParser, SurfaceControl.Builder::new,
- SurfaceControl.Transaction::new, WindowContainerTransaction::new,
- SurfaceControl::new, new SurfaceControlViewHostFactory() {},
- DefaultMaximizeMenuFactory.INSTANCE, DefaultHandleMenuFactory.INSTANCE,
- multiInstanceHelper);
+ rootTaskDisplayAreaOrganizer, genericLinksParser, assistContentRequester,
+ SurfaceControl.Builder::new, SurfaceControl.Transaction::new,
+ WindowContainerTransaction::new, SurfaceControl::new, new WindowManagerWrapper(
+ context.getSystemService(WindowManager.class)),
+ new SurfaceControlViewHostFactory() {}, DefaultMaximizeMenuFactory.INSTANCE,
+ DefaultHandleMenuFactory.INSTANCE, multiInstanceHelper);
}
DesktopModeWindowDecoration(
@@ -207,10 +215,12 @@
SyncTransactionQueue syncQueue,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
AppToWebGenericLinksParser genericLinksParser,
+ AssistContentRequester assistContentRequester,
Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
Supplier<WindowContainerTransaction> windowContainerTransactionSupplier,
Supplier<SurfaceControl> surfaceControlSupplier,
+ WindowManagerWrapper windowManagerWrapper,
SurfaceControlViewHostFactory surfaceControlViewHostFactory,
MaximizeMenuFactory maximizeMenuFactory,
HandleMenuFactory handleMenuFactory,
@@ -226,9 +236,11 @@
mSyncQueue = syncQueue;
mRootTaskDisplayAreaOrganizer = rootTaskDisplayAreaOrganizer;
mGenericLinksParser = genericLinksParser;
+ mAssistContentRequester = assistContentRequester;
mMaximizeMenuFactory = maximizeMenuFactory;
mHandleMenuFactory = handleMenuFactory;
mMultiInstanceHelper = multiInstanceHelper;
+ mWindowManagerWrapper = windowManagerWrapper;
}
/**
@@ -473,10 +485,18 @@
@Nullable
private Uri getBrowserLink() {
+ // Do not show browser link in browser applications
+ final ComponentName baseActivity = mTaskInfo.baseActivity;
+ if (baseActivity != null && AppToWebUtils.isBrowserApp(mContext,
+ baseActivity.getPackageName(), mUserContext.getUserId())) {
+ return null;
+ }
// If the captured link is available and has not expired, return the captured link.
// Otherwise, return the generic link which is set to null if a generic link is unavailable.
if (mCapturedLink != null && !mCapturedLink.mExpired) {
return mCapturedLink.mUri;
+ } else if (mWebUri != null) {
+ return mWebUri;
}
return mGenericLink;
}
@@ -574,7 +594,8 @@
return new AppHandleViewHolder(
mResult.mRootView,
mOnCaptionTouchListener,
- mOnCaptionButtonClickListener
+ mOnCaptionButtonClickListener,
+ mWindowManagerWrapper
);
} else if (mRelayoutParams.mLayoutResId
== R.layout.desktop_mode_app_header) {
@@ -981,17 +1002,32 @@
}
/**
- * Create and display handle menu window.
+ * Updates app info and creates and displays handle menu window.
*/
- void createHandleMenu(SplitScreenController splitScreenController) {
+ void createHandleMenu() {
+ // Requests assist content. When content is received, calls {@link #onAssistContentReceived}
+ // which sets app info and creates the handle menu.
+ mAssistContentRequester.requestAssistContent(
+ mTaskInfo.taskId, this::onAssistContentReceived);
+ }
+
+ /**
+ * Called when assist content is received. updates the saved links and creates the handle menu.
+ */
+ @VisibleForTesting
+ void onAssistContentReceived(@Nullable AssistContent assistContent) {
+ mWebUri = assistContent == null ? null : assistContent.getWebUri();
loadAppInfoIfNeeded();
updateGenericLink();
+
+ // Create and display handle menu
mHandleMenu = mHandleMenuFactory.create(
this,
+ mWindowManagerWrapper,
mRelayoutParams.mLayoutResId,
mAppIconBitmap,
mAppName,
- splitScreenController,
+ mSplitScreenController,
DesktopModeStatus.canEnterDesktopMode(mContext),
Flags.enableDesktopWindowingMultiInstanceFeatures()
&& mMultiInstanceHelper
@@ -1005,6 +1041,7 @@
mHandleMenu.show(
/* onToDesktopClickListener= */ () -> {
mOnToDesktopClickListener.accept(APP_HANDLE_MENU_BUTTON);
+ mOnToDesktopClickListener.accept(APP_HANDLE_MENU_BUTTON);
return Unit.INSTANCE;
},
/* onToFullscreenClickListener= */ mOnToFullscreenClickListener,
@@ -1326,6 +1363,7 @@
SyncTransactionQueue syncQueue,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
AppToWebGenericLinksParser genericLinksParser,
+ AssistContentRequester assistContentRequester,
MultiInstanceHelper multiInstanceHelper) {
return new DesktopModeWindowDecoration(
context,
@@ -1341,6 +1379,7 @@
syncQueue,
rootTaskDisplayAreaOrganizer,
genericLinksParser,
+ assistContentRequester,
multiInstanceHelper);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
index 34de94e..748046e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
@@ -64,6 +64,7 @@
*/
class HandleMenu(
private val parentDecor: DesktopModeWindowDecoration,
+ private val windowManagerWrapper: WindowManagerWrapper,
private val layoutResId: Int,
private val appIconBitmap: Bitmap?,
private val appName: CharSequence?,
@@ -178,7 +179,7 @@
handleMenuViewContainer =
if (!taskInfo.isFreeform && Flags.enableAdditionalWindowsAboveStatusBar()) {
AdditionalSystemViewContainer(
- context = context,
+ windowManagerWrapper = windowManagerWrapper,
taskId = taskInfo.taskId,
x = x,
y = y,
@@ -635,6 +636,7 @@
interface HandleMenuFactory {
fun create(
parentDecor: DesktopModeWindowDecoration,
+ windowManagerWrapper: WindowManagerWrapper,
layoutResId: Int,
appIconBitmap: Bitmap?,
appName: CharSequence?,
@@ -652,6 +654,7 @@
object DefaultHandleMenuFactory : HandleMenuFactory {
override fun create(
parentDecor: DesktopModeWindowDecoration,
+ windowManagerWrapper: WindowManagerWrapper,
layoutResId: Int,
appIconBitmap: Bitmap?,
appName: CharSequence?,
@@ -665,6 +668,7 @@
): HandleMenu {
return HandleMenu(
parentDecor,
+ windowManagerWrapper,
layoutResId,
appIconBitmap,
appName,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.kt
index fd6c4d8..fb81ed4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.kt
@@ -30,7 +30,6 @@
import android.view.LayoutInflater
import android.view.SurfaceControl
import android.view.SurfaceControlViewHost
-import android.view.SurfaceSession
import android.view.WindowManager
import android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL
import android.view.WindowlessWindowManager
@@ -66,7 +65,6 @@
private val lightColors = dynamicLightColorScheme(context)
private val darkColors = dynamicDarkColorScheme(context)
- private val surfaceSession = SurfaceSession()
private lateinit var iconView: ImageView
private var iconSize = 0
@@ -126,7 +124,7 @@
.setCallsite("ResizeVeil#setupResizeVeil")
.build()
backgroundSurface = surfaceControlBuilderFactory
- .create("Resize veil background of Task=" + taskInfo.taskId, surfaceSession)
+ .create("Resize veil background of Task=" + taskInfo.taskId)
.setColorLayer()
.setHidden(true)
.setParent(veilSurface)
@@ -399,10 +397,6 @@
fun create(name: String): SurfaceControl.Builder {
return SurfaceControl.Builder().setName(name)
}
-
- fun create(name: String, surfaceSession: SurfaceSession): SurfaceControl.Builder {
- return SurfaceControl.Builder(surfaceSession).setName(name)
- }
}
companion object {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowManagerWrapper.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowManagerWrapper.kt
new file mode 100644
index 0000000..5c2ff1b
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowManagerWrapper.kt
@@ -0,0 +1,41 @@
+/*
+ * 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.windowdecor
+
+import android.view.View
+import android.view.WindowManager
+
+/**
+ * A wrapper for [WindowManager] to make view manipulation operations related to window
+ * decors more testable.
+ */
+class WindowManagerWrapper (
+ private val windowManager: WindowManager
+){
+
+ fun addView(v: View, lp: WindowManager.LayoutParams) {
+ windowManager.addView(v, lp)
+ }
+
+ fun removeViewImmediate(v: View) {
+ windowManager.removeViewImmediate(v)
+ }
+
+ fun updateViewLayout(v: View, lp: WindowManager.LayoutParams) {
+ windowManager.updateViewLayout(v, lp)
+ }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainer.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainer.kt
index cadd80e..226b0fb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainer.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainer.kt
@@ -24,13 +24,14 @@
import android.view.SurfaceControl
import android.view.View
import android.view.WindowManager
+import com.android.wm.shell.windowdecor.WindowManagerWrapper
/**
* An [AdditionalViewContainer] that uses the system [WindowManager] instance. Intended
* for view containers that should be above the status bar layer.
*/
class AdditionalSystemViewContainer(
- context: Context,
+ private val windowManagerWrapper: WindowManagerWrapper,
taskId: Int,
x: Int,
y: Int,
@@ -39,9 +40,20 @@
flags: Int,
override val view: View
) : AdditionalViewContainer() {
+ val lp: WindowManager.LayoutParams = WindowManager.LayoutParams(
+ width, height, x, y,
+ WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL,
+ flags,
+ PixelFormat.TRANSPARENT
+ ).apply {
+ title = "Additional view container of Task=$taskId"
+ gravity = Gravity.LEFT or Gravity.TOP
+ setTrustedOverlay()
+ }
constructor(
context: Context,
+ windowManagerWrapper: WindowManagerWrapper,
taskId: Int,
x: Int,
y: Int,
@@ -50,7 +62,7 @@
flags: Int,
@LayoutRes layoutId: Int
) : this(
- context = context,
+ windowManagerWrapper = windowManagerWrapper,
taskId = taskId,
x = x,
y = y,
@@ -61,9 +73,16 @@
)
constructor(
- context: Context, taskId: Int, x: Int, y: Int, width: Int, height: Int, flags: Int
+ context: Context,
+ windowManagerWrapper: WindowManagerWrapper,
+ taskId: Int,
+ x: Int,
+ y: Int,
+ width: Int,
+ height: Int,
+ flags: Int
) : this(
- context = context,
+ windowManagerWrapper = windowManagerWrapper,
taskId = taskId,
x = x,
y = y,
@@ -73,24 +92,12 @@
view = View(context)
)
- val windowManager: WindowManager? = context.getSystemService(WindowManager::class.java)
-
init {
- val lp = WindowManager.LayoutParams(
- width, height, x, y,
- WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL,
- flags,
- PixelFormat.TRANSPARENT
- ).apply {
- title = "Additional view container of Task=$taskId"
- gravity = Gravity.LEFT or Gravity.TOP
- setTrustedOverlay()
- }
- windowManager?.addView(view, lp)
+ windowManagerWrapper.addView(view, lp)
}
override fun releaseView() {
- windowManager?.removeViewImmediate(view)
+ windowManagerWrapper.removeViewImmediate(view)
}
override fun setPosition(t: SurfaceControl.Transaction, x: Float, y: Float) {
@@ -98,6 +105,6 @@
this.x = x.toInt()
this.y = y.toInt()
}
- windowManager?.updateViewLayout(view, lp)
+ windowManagerWrapper.updateViewLayout(view, lp)
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt
index 510032b..9ef4b8c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt
@@ -29,9 +29,11 @@
import android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS
import android.view.WindowManager
import android.widget.ImageButton
+import com.android.internal.policy.SystemBarUtils
import com.android.window.flags.Flags
import com.android.wm.shell.R
import com.android.wm.shell.shared.animation.Interpolators
+import com.android.wm.shell.windowdecor.WindowManagerWrapper
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer
/**
@@ -41,14 +43,14 @@
internal class AppHandleViewHolder(
rootView: View,
onCaptionTouchListener: View.OnTouchListener,
- onCaptionButtonClickListener: OnClickListener
+ onCaptionButtonClickListener: OnClickListener,
+ private val windowManagerWrapper: WindowManagerWrapper
) : WindowDecorationViewHolder(rootView) {
companion object {
private const val CAPTION_HANDLE_ANIMATION_DURATION: Long = 100
}
private lateinit var taskInfo: RunningTaskInfo
- private val windowManager = context.getSystemService(WindowManager::class.java)
private val captionView: View = rootView.requireViewById(R.id.desktop_mode_caption)
private val captionHandle: ImageButton = rootView.requireViewById(R.id.caption_handle)
private val inputManager = context.getSystemService(InputManager::class.java)
@@ -73,7 +75,10 @@
) {
captionHandle.imageTintList = ColorStateList.valueOf(getCaptionHandleBarColor(taskInfo))
this.taskInfo = taskInfo
- if (!isCaptionVisible && hasStatusBarInputLayer()) {
+ // If handle is not in status bar region(i.e., bottom stage in vertical split),
+ // do not create an input layer
+ if (position.y >= SystemBarUtils.getStatusBarHeight(context)) return
+ if (!isCaptionVisible && hasStatusBarInputLayer() ) {
disposeStatusBarInputLayer()
return
}
@@ -96,11 +101,12 @@
handleWidth: Int,
handleHeight: Int) {
if (!Flags.enableAdditionalWindowsAboveStatusBar()) return
- statusBarInputLayer = AdditionalSystemViewContainer(context, taskInfo.taskId,
- handlePosition.x, handlePosition.y, handleWidth, handleHeight,
+ statusBarInputLayer = AdditionalSystemViewContainer(context, windowManagerWrapper,
+ taskInfo.taskId, handlePosition.x, handlePosition.y, handleWidth, handleHeight,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
- val view = statusBarInputLayer?.view
- val lp = view?.layoutParams as WindowManager.LayoutParams
+ val view = statusBarInputLayer?.view ?: error("Unable to find statusBarInputLayer View")
+ val lp = statusBarInputLayer?.lp ?: error("Unable to find statusBarInputLayer" +
+ "LayoutParams")
lp.title = "Handle Input Layer of task " + taskInfo.taskId
lp.setTrustedOverlay()
// Make this window a spy window to enable it to pilfer pointers from the system-wide
@@ -118,9 +124,9 @@
inputManager.pilferPointers(v.viewRootImpl.inputToken)
}
captionHandle.dispatchTouchEvent(event)
- true
+ return@setOnTouchListener true
}
- windowManager.updateViewLayout(view, lp)
+ windowManagerWrapper.updateViewLayout(view, lp)
}
private fun updateStatusBarInputLayer(globalPosition: Point) {
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
index 880e021..7640cb1 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
@@ -16,12 +16,15 @@
package com.android.wm.shell.flicker
+import android.tools.PlatformConsts.DESKTOP_MODE_MINIMUM_WINDOW_HEIGHT
+import android.tools.PlatformConsts.DESKTOP_MODE_MINIMUM_WINDOW_WIDTH
import android.tools.flicker.AssertionInvocationGroup
import android.tools.flicker.assertors.assertions.AppLayerIncreasesInSize
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.AppWindowBecomesVisible
+import android.tools.flicker.assertors.assertions.AppWindowAlignsWithOnlyOneDisplayCornerAtEnd
import android.tools.flicker.assertors.assertions.AppWindowCoversLeftHalfScreenAtEnd
import android.tools.flicker.assertors.assertions.AppWindowCoversRightHalfScreenAtEnd
import android.tools.flicker.assertors.assertions.AppWindowHasDesktopModeInitialBoundsAtTheEnd
@@ -29,6 +32,7 @@
import android.tools.flicker.assertors.assertions.AppWindowHasMaxDisplayHeight
import android.tools.flicker.assertors.assertions.AppWindowHasMaxDisplayWidth
import android.tools.flicker.assertors.assertions.AppWindowHasSizeOfAtLeast
+import android.tools.flicker.assertors.assertions.AppWindowInsideDisplayBoundsAtEnd
import android.tools.flicker.assertors.assertions.AppWindowIsInvisibleAtEnd
import android.tools.flicker.assertors.assertions.AppWindowIsVisibleAlways
import android.tools.flicker.assertors.assertions.AppWindowMaintainsAspectRatioAlways
@@ -181,10 +185,35 @@
.build(),
assertions =
AssertionTemplates.DESKTOP_MODE_APP_VISIBILITY_ASSERTIONS +
- listOf(AppWindowHasSizeOfAtLeast(DESKTOP_MODE_APP, 770, 700))
+ listOf(
+ AppWindowHasSizeOfAtLeast(
+ DESKTOP_MODE_APP,
+ DESKTOP_MODE_MINIMUM_WINDOW_WIDTH,
+ DESKTOP_MODE_MINIMUM_WINDOW_HEIGHT
+ )
+ )
.associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
)
+ val CORNER_RESIZE_TO_MAXIMUM_SIZE =
+ FlickerConfigEntry(
+ scenarioId = ScenarioId("CORNER_RESIZE_TO_MAXIMUM_SIZE"),
+ extractor =
+ TaggedScenarioExtractorBuilder()
+ .setTargetTag(CujType.CUJ_DESKTOP_MODE_RESIZE_WINDOW)
+ .setTransitionMatcher(
+ TaggedCujTransitionMatcher(associatedTransitionRequired = false)
+ )
+ .build(),
+ assertions =
+ AssertionTemplates.DESKTOP_MODE_APP_VISIBILITY_ASSERTIONS +
+ listOf(
+ AppLayerIncreasesInSize(DESKTOP_MODE_APP),
+ AppWindowHasMaxDisplayHeight(DESKTOP_MODE_APP),
+ AppWindowHasMaxDisplayWidth(DESKTOP_MODE_APP)
+ ).associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
+ )
+
val SNAP_RESIZE_LEFT_WITH_BUTTON =
FlickerConfigEntry(
scenarioId = ScenarioId("SNAP_RESIZE_LEFT_WITH_BUTTON"),
@@ -300,5 +329,28 @@
AppWindowHasMaxBoundsInOnlyOneDimension(DESKTOP_MODE_APP)
).associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
)
+
+ val CASCADE_APP =
+ FlickerConfigEntry(
+ scenarioId = ScenarioId("CASCADE_APP"),
+ extractor =
+ ShellTransitionScenarioExtractor(
+ transitionMatcher =
+ object : ITransitionMatcher {
+ override fun findAll(
+ transitions: Collection<Transition>
+ ): Collection<Transition> {
+ return transitions.filter { it.type == TransitionType.OPEN }
+ }
+ }
+ ),
+ assertions =
+ listOf(
+ AppWindowInsideDisplayBoundsAtEnd(DESKTOP_MODE_APP),
+ AppWindowOnTopAtEnd(DESKTOP_MODE_APP),
+ AppWindowBecomesVisible(DESKTOP_MODE_APP),
+ AppWindowAlignsWithOnlyOneDisplayCornerAtEnd(DESKTOP_MODE_APP)
+ ).associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
+ )
}
}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/OpenAppsInDesktopModeLandscape.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/OpenAppsInDesktopModeLandscape.kt
new file mode 100644
index 0000000..a07fa99
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/OpenAppsInDesktopModeLandscape.kt
@@ -0,0 +1,43 @@
+/*
+ * 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
+
+import android.tools.Rotation.ROTATION_90
+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.DesktopModeFlickerScenarios.Companion.CASCADE_APP
+import com.android.wm.shell.scenarios.OpenAppsInDesktopMode
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class OpenAppsInDesktopModeLandscape : OpenAppsInDesktopMode(rotation = ROTATION_90) {
+ @ExpectedScenarios(["CASCADE_APP"])
+ @Test
+ override fun openApps() = super.openApps()
+
+ companion object {
+ @JvmStatic
+ @FlickerConfigProvider
+ fun flickerConfigProvider(): FlickerConfig =
+ FlickerConfig().use(FlickerServiceConfig.DEFAULT).use(CASCADE_APP)
+ }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/OpenAppsInDesktopModePortrait.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/OpenAppsInDesktopModePortrait.kt
new file mode 100644
index 0000000..c7a958a
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/OpenAppsInDesktopModePortrait.kt
@@ -0,0 +1,42 @@
+/*
+ * 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
+
+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.DesktopModeFlickerScenarios.Companion.CASCADE_APP
+import com.android.wm.shell.scenarios.OpenAppsInDesktopMode
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class OpenAppsInDesktopModePortrait : OpenAppsInDesktopMode() {
+ @ExpectedScenarios(["CASCADE_APP"])
+ @Test
+ override fun openApps() = super.openApps()
+
+ companion object {
+ @JvmStatic
+ @FlickerConfigProvider
+ fun flickerConfigProvider(): FlickerConfig =
+ FlickerConfig().use(FlickerServiceConfig.DEFAULT).use(CASCADE_APP)
+ }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizeLandscape.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizeLandscape.kt
new file mode 100644
index 0000000..0b98ba2
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizeLandscape.kt
@@ -0,0 +1,52 @@
+/*
+ * 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
+
+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.DesktopModeFlickerScenarios.Companion.CORNER_RESIZE_TO_MAXIMUM_SIZE
+import com.android.wm.shell.scenarios.ResizeAppWithCornerResize
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Resize app window using corner resize to the greatest possible height and width in
+ * landscape mode.
+ *
+ * Assert that the maximum window size constraint is maintained.
+ */
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class ResizeAppToMaximumWindowSizeLandscape : ResizeAppWithCornerResize(
+ rotation = Rotation.ROTATION_90
+) {
+ @ExpectedScenarios(["CORNER_RESIZE_TO_MAXIMUM_SIZE"])
+ @Test
+ override fun resizeAppWithCornerResizeToMaximumSize() =
+ super.resizeAppWithCornerResizeToMaximumSize()
+
+ companion object {
+ @JvmStatic
+ @FlickerConfigProvider
+ fun flickerConfigProvider(): FlickerConfig =
+ FlickerConfig().use(FlickerServiceConfig.DEFAULT).use(CORNER_RESIZE_TO_MAXIMUM_SIZE)
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizePortrait.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizePortrait.kt
new file mode 100644
index 0000000..b1c04d3
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizePortrait.kt
@@ -0,0 +1,49 @@
+/*
+ * 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
+
+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.DesktopModeFlickerScenarios.Companion.CORNER_RESIZE_TO_MAXIMUM_SIZE
+import com.android.wm.shell.scenarios.ResizeAppWithCornerResize
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Resize app window using corner resize to the greatest possible height and width in
+ * portrait mode.
+ *
+ * Assert that the maximum window size constraint is maintained.
+ */
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class ResizeAppToMaximumWindowSizePortrait : ResizeAppWithCornerResize() {
+ @ExpectedScenarios(["CORNER_RESIZE_TO_MAXIMUM_SIZE"])
+ @Test
+ override fun resizeAppWithCornerResizeToMaximumSize() =
+ super.resizeAppWithCornerResizeToMaximumSize()
+
+ companion object {
+ @JvmStatic
+ @FlickerConfigProvider
+ fun flickerConfigProvider(): FlickerConfig =
+ FlickerConfig().use(FlickerServiceConfig.DEFAULT).use(CORNER_RESIZE_TO_MAXIMUM_SIZE)
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/CloseAllAppsWithAppHeaderExitTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/CloseAllAppsWithAppHeaderExitTest.kt
new file mode 100644
index 0000000..a4dc52b
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/CloseAllAppsWithAppHeaderExitTest.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.CloseAllAppsWithAppHeaderExit
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [CloseAllAppsWithAppHeaderExit]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class CloseAllAppsWithAppHeaderExitTest() : CloseAllAppsWithAppHeaderExit()
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceLoggerKosmos.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/EnterDesktopWithDragTest.kt
similarity index 60%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceLoggerKosmos.kt
copy to libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/EnterDesktopWithDragTest.kt
index 76d71dd..3d95f97 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceLoggerKosmos.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/EnterDesktopWithDragTest.kt
@@ -14,10 +14,14 @@
* limitations under the License.
*/
-package com.android.systemui.media.controls.domain.pipeline
+package com.android.wm.shell.functional
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.log.logcatLogBuffer
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.EnterDesktopWithDrag
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
-var Kosmos.mediaDeviceLogger by
- Kosmos.Fixture { MediaDeviceLogger(logcatLogBuffer("MediaDeviceLoggerKosmos")) }
+/* Functional test for [EnterDesktopWithDrag]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class EnterDesktopWithDragTest : EnterDesktopWithDrag()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ExitDesktopWithDragToTopDragZoneTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ExitDesktopWithDragToTopDragZoneTest.kt
new file mode 100644
index 0000000..140c5ec
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ExitDesktopWithDragToTopDragZoneTest.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.ExitDesktopWithDragToTopDragZone
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [ExitDesktopWithDragToTopDragZone]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class ExitDesktopWithDragToTopDragZoneTest : ExitDesktopWithDragToTopDragZone()
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceLoggerKosmos.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/MaximizeAppWindowTest.kt
similarity index 61%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceLoggerKosmos.kt
copy to libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/MaximizeAppWindowTest.kt
index 76d71dd..3d3dcd0 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceLoggerKosmos.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/MaximizeAppWindowTest.kt
@@ -14,10 +14,14 @@
* limitations under the License.
*/
-package com.android.systemui.media.controls.domain.pipeline
+package com.android.wm.shell.functional
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.log.logcatLogBuffer
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.MaximizeAppWindow
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
-var Kosmos.mediaDeviceLogger by
- Kosmos.Fixture { MediaDeviceLogger(logcatLogBuffer("MediaDeviceLoggerKosmos")) }
+/* Functional test for [MaximizeAppWindow]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class MaximizeAppWindowTest : MaximizeAppWindow()
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceLoggerKosmos.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/OpenAppsInDesktopModeTest.kt
similarity index 60%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceLoggerKosmos.kt
copy to libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/OpenAppsInDesktopModeTest.kt
index 76d71dd..263e89f6 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceLoggerKosmos.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/OpenAppsInDesktopModeTest.kt
@@ -14,10 +14,14 @@
* limitations under the License.
*/
-package com.android.systemui.media.controls.domain.pipeline
+package com.android.wm.shell.functional
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.log.logcatLogBuffer
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.OpenAppsInDesktopMode
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
-var Kosmos.mediaDeviceLogger by
- Kosmos.Fixture { MediaDeviceLogger(logcatLogBuffer("MediaDeviceLoggerKosmos")) }
+/* Functional test for [OpenAppsInDesktopMode]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class OpenAppsInDesktopModeTest : OpenAppsInDesktopMode()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppCornerMultiWindowAndPipTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppCornerMultiWindowAndPipTest.kt
new file mode 100644
index 0000000..13f4775
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppCornerMultiWindowAndPipTest.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.ResizeAppCornerMultiWindowAndPip
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [ResizeAppCornerMultiWindowAndPip]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class ResizeAppCornerMultiWindowAndPipTest : ResizeAppCornerMultiWindowAndPip()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppCornerMultiWindowTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppCornerMultiWindowTest.kt
new file mode 100644
index 0000000..bc9bb41
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppCornerMultiWindowTest.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.ResizeAppCornerMultiWindow
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [ResizeAppCornerMultiWindow]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class ResizeAppCornerMultiWindowTest : ResizeAppCornerMultiWindow()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppWithCornerResizeTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppWithCornerResizeTest.kt
new file mode 100644
index 0000000..46168eb
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppWithCornerResizeTest.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.ResizeAppWithCornerResize
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [ResizeAppWithCornerResize]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class ResizeAppWithCornerResizeTest : ResizeAppWithCornerResize()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppWithEdgeResizeTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppWithEdgeResizeTest.kt
new file mode 100644
index 0000000..ee24200
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/ResizeAppWithEdgeResizeTest.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.server.wm.flicker.helpers.MotionEventHelper
+import com.android.wm.shell.scenarios.ResizeAppWithEdgeResize
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [ResizeAppWithEdgeResize]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class ResizeAppWithEdgeResizeTest :
+ ResizeAppWithEdgeResize(MotionEventHelper.InputMethod.TOUCHPAD)
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/SnapResizeAppWindowWithButtonTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/SnapResizeAppWindowWithButtonTest.kt
new file mode 100644
index 0000000..38e85c7
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/SnapResizeAppWindowWithButtonTest.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.SnapResizeAppWindowWithButton
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [SnapResizeAppWindowWithButton]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class SnapResizeAppWindowWithButtonTest : SnapResizeAppWindowWithButton()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/SnapResizeAppWindowWithDragTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/SnapResizeAppWindowWithDragTest.kt
new file mode 100644
index 0000000..082a3fb
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/SnapResizeAppWindowWithDragTest.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.SnapResizeAppWindowWithDrag
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [SnapResizeAppWindowWithDrag]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class SnapResizeAppWindowWithDragTest : SnapResizeAppWindowWithDrag()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/SwitchToOverviewFromDesktopTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/SwitchToOverviewFromDesktopTest.kt
new file mode 100644
index 0000000..fdd0d81
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/SwitchToOverviewFromDesktopTest.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.SwitchToOverviewFromDesktop
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [SwitchToOverviewFromDesktop]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class SwitchToOverviewFromDesktopTest : SwitchToOverviewFromDesktop()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/CloseAllAppsWithAppHeaderExit.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/CloseAllAppsWithAppHeaderExit.kt
index e9056f3..351a700 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/CloseAllAppsWithAppHeaderExit.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/CloseAllAppsWithAppHeaderExit.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.scenarios
-import android.platform.test.annotations.Postsubmit
import android.app.Instrumentation
import android.tools.NavBar
import android.tools.Rotation
@@ -33,15 +32,12 @@
import org.junit.After
import org.junit.Assume
import org.junit.Before
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class CloseAllAppsWithAppHeaderExit
-@JvmOverloads
+@Ignore("Base Test Class")
+abstract class CloseAllAppsWithAppHeaderExit
constructor(val rotation: Rotation = Rotation.ROTATION_0) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/DragAppWindowMultiWindow.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/DragAppWindowMultiWindow.kt
index ca1dc1a..3f9927f 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/DragAppWindowMultiWindow.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/DragAppWindowMultiWindow.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.scenarios
-import android.platform.test.annotations.Postsubmit
import com.android.server.wm.flicker.helpers.DesktopModeAppHelper
import com.android.server.wm.flicker.helpers.ImeAppHelper
import com.android.server.wm.flicker.helpers.MailAppHelper
@@ -26,13 +25,11 @@
import org.junit.After
import org.junit.Assume
import org.junit.Before
+import org.junit.Ignore
import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class DragAppWindowMultiWindow : DragAppWindowScenarioTestBase()
+@Ignore("Test Base Class")
+abstract class DragAppWindowMultiWindow : DragAppWindowScenarioTestBase()
{
private val imeAppHelper = ImeAppHelper(instrumentation)
private val testApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation))
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/EnterDesktopWithDrag.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/EnterDesktopWithDrag.kt
index 5f759e8..967bd29 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/EnterDesktopWithDrag.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/EnterDesktopWithDrag.kt
@@ -16,27 +16,24 @@
package com.android.wm.shell.scenarios
-import android.platform.test.annotations.Postsubmit
import android.tools.NavBar
import android.tools.Rotation
+import android.tools.flicker.rules.ChangeDisplayOrientationRule
import com.android.window.flags.Flags
import com.android.wm.shell.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
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class EnterDesktopWithDrag
-@JvmOverloads
+@Ignore("Test Base Class")
+abstract class EnterDesktopWithDrag
constructor(
val rotation: Rotation = Rotation.ROTATION_0,
isResizeable: Boolean = true,
- isLandscapeApp: Boolean = true
+ isLandscapeApp: Boolean = true,
) : DesktopScenarioCustomAppTestBase(isResizeable, isLandscapeApp) {
@Rule @JvmField val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, rotation)
@@ -46,6 +43,8 @@
Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
+ ChangeDisplayOrientationRule.setRotation(rotation)
+ tapl.enableTransientTaskbar(false)
}
@Test
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ExitDesktopWithDragToTopDragZone.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ExitDesktopWithDragToTopDragZone.kt
index b616e53..824c448 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ExitDesktopWithDragToTopDragZone.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ExitDesktopWithDragToTopDragZone.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.scenarios
-import android.platform.test.annotations.Postsubmit
import android.tools.NavBar
import android.tools.Rotation
import com.android.window.flags.Flags
@@ -24,19 +23,16 @@
import org.junit.After
import org.junit.Assume
import org.junit.Before
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class ExitDesktopWithDragToTopDragZone
-@JvmOverloads
+@Ignore("Test Base Class")
+abstract class ExitDesktopWithDragToTopDragZone
constructor(
val rotation: Rotation = Rotation.ROTATION_0,
isResizeable: Boolean = true,
- isLandscapeApp: Boolean = true
+ isLandscapeApp: Boolean = true,
) : DesktopScenarioCustomAppTestBase(isResizeable, isLandscapeApp) {
@Rule @JvmField val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, rotation)
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MaximizeAppWindow.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MaximizeAppWindow.kt
index 426f40b..a54d497 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MaximizeAppWindow.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MaximizeAppWindow.kt
@@ -17,7 +17,6 @@
package com.android.wm.shell.scenarios
import android.app.Instrumentation
-import android.platform.test.annotations.Postsubmit
import android.tools.NavBar
import android.tools.Rotation
import android.tools.flicker.rules.ChangeDisplayOrientationRule
@@ -33,15 +32,12 @@
import org.junit.After
import org.junit.Assume
import org.junit.Before
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class MaximizeAppWindow
-@JvmOverloads
+@Ignore("Test Base Class")
+abstract class MaximizeAppWindow
constructor(private val rotation: Rotation = Rotation.ROTATION_0, isResizable: Boolean = true) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/OpenAppsInDesktopMode.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/OpenAppsInDesktopMode.kt
new file mode 100644
index 0000000..aad266f
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/OpenAppsInDesktopMode.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.wm.shell.scenarios
+
+import android.app.Instrumentation
+import android.tools.flicker.rules.ChangeDisplayOrientationRule
+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.ImeAppHelper
+import com.android.server.wm.flicker.helpers.MailAppHelper
+import com.android.server.wm.flicker.helpers.NewTasksAppHelper
+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.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("Test Base Class")
+abstract class OpenAppsInDesktopMode(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 firstApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation))
+ private val secondApp = MailAppHelper(instrumentation)
+ private val thirdApp = NewTasksAppHelper(instrumentation)
+ private val fourthApp = ImeAppHelper(instrumentation)
+ private val fifthApp = NonResizeableAppHelper(instrumentation)
+
+ @Rule @JvmField val testSetupRule = Utils.testSetupRule(NavBar.MODE_3BUTTON, rotation)
+
+ @Before
+ fun setup() {
+ Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
+ tapl.setEnableRotation(true)
+ tapl.setExpectedRotation(rotation.value)
+ tapl.enableTransientTaskbar(false)
+ ChangeDisplayOrientationRule.setRotation(rotation)
+ firstApp.enterDesktopWithDrag(wmHelper, device)
+ }
+
+ @Test
+ open fun openApps() {
+ secondApp.launchViaIntent(wmHelper)
+ thirdApp.launchViaIntent(wmHelper)
+ fourthApp.launchViaIntent(wmHelper)
+ fifthApp.launchViaIntent(wmHelper)
+ }
+
+ @After
+ fun teardown() {
+ fifthApp.exit(wmHelper)
+ fourthApp.exit(wmHelper)
+ thirdApp.exit(wmHelper)
+ secondApp.exit(wmHelper)
+ firstApp.exit(wmHelper)
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindow.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindow.kt
index b6bca7a..bfee318 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindow.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindow.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.scenarios
-import android.platform.test.annotations.Postsubmit
import android.app.Instrumentation
import android.tools.NavBar
import android.tools.Rotation
@@ -34,15 +33,12 @@
import org.junit.After
import org.junit.Assume
import org.junit.Before
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class ResizeAppCornerMultiWindow
-@JvmOverloads
+@Ignore("Test Base Class")
+abstract class ResizeAppCornerMultiWindow
constructor(val rotation: Rotation = Rotation.ROTATION_0,
val horizontalChange: Int = 50,
val verticalChange: Int = -50) {
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindowAndPip.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindowAndPip.kt
index 285ea13..5b1b64e 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindowAndPip.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppCornerMultiWindowAndPip.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.scenarios
-import android.platform.test.annotations.Postsubmit
import android.app.Instrumentation
import android.tools.NavBar
import android.tools.Rotation
@@ -35,15 +34,12 @@
import org.junit.After
import org.junit.Assume
import org.junit.Before
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class ResizeAppCornerMultiWindowAndPip
-@JvmOverloads
+@Ignore("Test Base Class")
+abstract class ResizeAppCornerMultiWindowAndPip
constructor(val rotation: Rotation = Rotation.ROTATION_0,
val horizontalChange: Int = 50,
val verticalChange: Int = -50) {
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithCornerResize.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithCornerResize.kt
index 42940a9..bd25639 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithCornerResize.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithCornerResize.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.scenarios
-import android.platform.test.annotations.Postsubmit
import android.app.Instrumentation
import android.tools.NavBar
import android.tools.Rotation
@@ -32,16 +31,12 @@
import org.junit.After
import org.junit.Assume
import org.junit.Before
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class ResizeAppWithCornerResize
-@JvmOverloads
-constructor(
+@Ignore("Test Base Class")
+abstract class ResizeAppWithCornerResize(
val rotation: Rotation = Rotation.ROTATION_0,
val horizontalChange: Int = 200,
val verticalChange: Int = -200,
@@ -83,6 +78,25 @@
)
}
+ @Test
+ open fun resizeAppWithCornerResizeToMaximumSize() {
+ val maxResizeChange = 3000
+ testApp.cornerResize(
+ wmHelper,
+ device,
+ DesktopModeAppHelper.Corners.RIGHT_TOP,
+ maxResizeChange,
+ -maxResizeChange
+ )
+ testApp.cornerResize(
+ wmHelper,
+ device,
+ DesktopModeAppHelper.Corners.LEFT_BOTTOM,
+ -maxResizeChange,
+ maxResizeChange
+ )
+ }
+
@After
fun teardown() {
testApp.exit(wmHelper)
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithEdgeResize.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithEdgeResize.kt
index d094967..6780238 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithEdgeResize.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithEdgeResize.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.scenarios
-import android.platform.test.annotations.Postsubmit
import android.app.Instrumentation
import android.tools.NavBar
import android.tools.Rotation
@@ -32,15 +31,12 @@
import org.junit.After
import org.junit.Assume
import org.junit.Before
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class ResizeAppWithEdgeResize
-@JvmOverloads
+@Ignore("Test Base Class")
+abstract class ResizeAppWithEdgeResize
constructor(
val inputMethod: MotionEventHelper.InputMethod,
val rotation: Rotation = Rotation.ROTATION_90
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SnapResizeAppWindowWithButton.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SnapResizeAppWindowWithButton.kt
index 33242db..2b40497 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SnapResizeAppWindowWithButton.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SnapResizeAppWindowWithButton.kt
@@ -17,7 +17,6 @@
package com.android.wm.shell.scenarios
import android.app.Instrumentation
-import android.platform.test.annotations.Postsubmit
import android.tools.NavBar
import android.tools.Rotation
import android.tools.traces.parsers.WindowManagerStateHelper
@@ -32,15 +31,12 @@
import org.junit.After
import org.junit.Assume
import org.junit.Before
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class SnapResizeAppWindowWithButton
-@JvmOverloads
+@Ignore("Test Base Class")
+abstract class SnapResizeAppWindowWithButton
constructor(private val toLeft: Boolean = true, isResizable: Boolean = true) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SnapResizeAppWindowWithDrag.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SnapResizeAppWindowWithDrag.kt
index 14eb779..b4bd7e1 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SnapResizeAppWindowWithDrag.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SnapResizeAppWindowWithDrag.kt
@@ -17,7 +17,6 @@
package com.android.wm.shell.scenarios
import android.app.Instrumentation
-import android.platform.test.annotations.Postsubmit
import android.tools.NavBar
import android.tools.Rotation
import android.tools.traces.parsers.WindowManagerStateHelper
@@ -32,15 +31,12 @@
import org.junit.After
import org.junit.Assume
import org.junit.Before
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class SnapResizeAppWindowWithDrag
-@JvmOverloads
+@Ignore("Test Base Class")
+abstract class SnapResizeAppWindowWithDrag
constructor(private val toLeft: Boolean = true, isResizable: Boolean = true) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
@@ -72,4 +68,4 @@
fun teardown() {
testApp.exit(wmHelper)
}
-}
\ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SwitchToOverviewFromDesktop.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SwitchToOverviewFromDesktop.kt
index 53e36e23..dad2eb6 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SwitchToOverviewFromDesktop.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/SwitchToOverviewFromDesktop.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.scenarios
-import android.platform.test.annotations.Postsubmit
import android.app.Instrumentation
import android.tools.NavBar
import android.tools.Rotation
@@ -31,20 +30,17 @@
import org.junit.After
import org.junit.Assume
import org.junit.Before
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.BlockJUnit4ClassRunner
/**
* Base test for opening recent apps overview from desktop mode.
*
* Navigation mode can be passed as a constructor parameter, by default it is set to gesture navigation.
*/
-@RunWith(BlockJUnit4ClassRunner::class)
-@Postsubmit
-open class SwitchToOverviewFromDesktop
-@JvmOverloads
+@Ignore("Base Test Class")
+abstract class SwitchToOverviewFromDesktop
constructor(val navigationMode: NavBar = NavBar.MODE_GESTURAL) {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
diff --git a/libs/WindowManager/Shell/tests/unittest/Android.bp b/libs/WindowManager/Shell/tests/unittest/Android.bp
index 4d761e1..006a4a9 100644
--- a/libs/WindowManager/Shell/tests/unittest/Android.bp
+++ b/libs/WindowManager/Shell/tests/unittest/Android.bp
@@ -94,3 +94,10 @@
"com.android.wm.shell.tests",
],
}
+
+test_module_config {
+ name: "WMShellUnitTests_shell_back",
+ base: "WMShellUnitTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.wm.shell.back"],
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
index 413e495..e514dc3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
@@ -49,7 +49,6 @@
import android.os.RemoteException;
import android.util.SparseArray;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
import android.window.ITaskOrganizer;
import android.window.ITaskOrganizerController;
import android.window.TaskAppearedInfo;
@@ -169,7 +168,7 @@
public void testTaskLeashReleasedAfterVanished() throws RemoteException {
assumeFalse(ENABLE_SHELL_TRANSITIONS);
RunningTaskInfo taskInfo = createTaskInfo(/* taskId= */ 1, WINDOWING_MODE_MULTI_WINDOW);
- SurfaceControl taskLeash = new SurfaceControl.Builder(new SurfaceSession())
+ SurfaceControl taskLeash = new SurfaceControl.Builder()
.setName("task").build();
mOrganizer.registerOrganizer();
mOrganizer.onTaskAppeared(taskInfo, taskLeash);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
index a8d40db..386253c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
@@ -46,6 +46,7 @@
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
+import android.app.KeyguardManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -136,6 +137,8 @@
mMainExecutor = new TestShellExecutor();
when(mContext.getPackageManager()).thenReturn(mock(PackageManager.class));
+ when(mContext.getSystemService(KeyguardManager.class))
+ .thenReturn(mock(KeyguardManager.class));
mShellInit = spy(new ShellInit(mMainExecutor));
mShellController = spy(new ShellController(mContext, mShellInit, mShellCommandHandler,
mDisplayInsetsController, mMainExecutor));
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java
deleted file mode 100644
index b1befc4..0000000
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.splitscreen;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.ActivityManager;
-import android.view.SurfaceControl;
-import android.view.SurfaceSession;
-import android.window.WindowContainerTransaction;
-
-import androidx.test.annotation.UiThreadTest;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.launcher3.icons.IconProvider;
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.ShellTestCase;
-import com.android.wm.shell.TestRunningTaskInfoBuilder;
-import com.android.wm.shell.common.SyncTransactionQueue;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.Optional;
-
-/** Tests for {@link MainStage} */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class MainStageTests extends ShellTestCase {
- @Mock private ShellTaskOrganizer mTaskOrganizer;
- @Mock private StageTaskListener.StageListenerCallbacks mCallbacks;
- @Mock private SyncTransactionQueue mSyncQueue;
- @Mock private ActivityManager.RunningTaskInfo mRootTaskInfo;
- @Mock private SurfaceControl mRootLeash;
- @Mock private IconProvider mIconProvider;
- private WindowContainerTransaction mWct = new WindowContainerTransaction();
- private SurfaceSession mSurfaceSession = new SurfaceSession();
- private MainStage mMainStage;
-
- @Before
- @UiThreadTest
- public void setup() {
- MockitoAnnotations.initMocks(this);
- mRootTaskInfo = new TestRunningTaskInfoBuilder().build();
- mMainStage = new MainStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks,
- mSyncQueue, mSurfaceSession, mIconProvider, Optional.empty());
- mMainStage.onTaskAppeared(mRootTaskInfo, mRootLeash);
- }
-
- @Test
- public void testActiveDeactivate() {
- mMainStage.activate(mWct, true /* reparent */);
- assertThat(mMainStage.isActive()).isTrue();
-
- mMainStage.deactivate(mWct);
- assertThat(mMainStage.isActive()).isFalse();
- }
-}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java
deleted file mode 100644
index 549bd3f..0000000
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.splitscreen;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.isNull;
-import static org.mockito.Mockito.verify;
-
-import android.app.ActivityManager;
-import android.view.SurfaceControl;
-import android.view.SurfaceSession;
-import android.window.WindowContainerTransaction;
-
-import androidx.test.annotation.UiThreadTest;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.launcher3.icons.IconProvider;
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.ShellTestCase;
-import com.android.wm.shell.TestRunningTaskInfoBuilder;
-import com.android.wm.shell.common.SyncTransactionQueue;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.Spy;
-
-import java.util.Optional;
-
-/** Tests for {@link SideStage} */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class SideStageTests extends ShellTestCase {
- @Mock private ShellTaskOrganizer mTaskOrganizer;
- @Mock private StageTaskListener.StageListenerCallbacks mCallbacks;
- @Mock private SyncTransactionQueue mSyncQueue;
- @Mock private ActivityManager.RunningTaskInfo mRootTask;
- @Mock private SurfaceControl mRootLeash;
- @Mock private IconProvider mIconProvider;
- @Spy private WindowContainerTransaction mWct;
- private SurfaceSession mSurfaceSession = new SurfaceSession();
- private SideStage mSideStage;
-
- @Before
- @UiThreadTest
- public void setup() {
- MockitoAnnotations.initMocks(this);
- mRootTask = new TestRunningTaskInfoBuilder().build();
- mSideStage = new SideStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks,
- mSyncQueue, mSurfaceSession, mIconProvider, Optional.empty());
- mSideStage.onTaskAppeared(mRootTask, mRootLeash);
- }
-
- @Test
- public void testAddTask() {
- final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
-
- mSideStage.addTask(task, mWct);
-
- verify(mWct).reparent(eq(task.token), eq(mRootTask.token), eq(true));
- }
-
- @Test
- public void testRemoveTask() {
- final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
- assertThat(mSideStage.removeTask(task.taskId, null, mWct)).isFalse();
-
- mSideStage.mChildrenTaskInfo.put(task.taskId, task);
- assertThat(mSideStage.removeTask(task.taskId, null, mWct)).isTrue();
- verify(mWct).reparent(eq(task.token), isNull(), eq(false));
- }
-}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java
index aa96c45..66dcef6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java
@@ -24,7 +24,6 @@
import android.graphics.Rect;
import android.os.Handler;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -74,10 +73,10 @@
final SurfaceControl mRootLeash;
TestStageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
- ShellTaskOrganizer taskOrganizer, MainStage mainStage, SideStage sideStage,
- DisplayController displayController, DisplayImeController imeController,
- DisplayInsetsController insetsController, SplitLayout splitLayout,
- Transitions transitions, TransactionPool transactionPool,
+ ShellTaskOrganizer taskOrganizer, StageTaskListener mainStage,
+ StageTaskListener sideStage, DisplayController displayController,
+ DisplayImeController imeController, DisplayInsetsController insetsController,
+ SplitLayout splitLayout, Transitions transitions, TransactionPool transactionPool,
ShellExecutor mainExecutor, Handler mainHandler,
Optional<RecentTasksController> recentTasks,
LaunchAdjacentController launchAdjacentController,
@@ -89,7 +88,7 @@
// Prepare root task for testing.
mRootTask = new TestRunningTaskInfoBuilder().build();
- mRootLeash = new SurfaceControl.Builder(new SurfaceSession()).setName("test").build();
+ mRootLeash = new SurfaceControl.Builder().setName("test").build();
onTaskAppeared(mRootTask, mRootLeash);
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
index abe3dcc..ce3944a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
@@ -53,7 +53,6 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
import android.window.IRemoteTransition;
import android.window.RemoteTransition;
import android.window.TransitionInfo;
@@ -106,7 +105,6 @@
@Mock private DisplayInsetsController mDisplayInsetsController;
@Mock private TransactionPool mTransactionPool;
@Mock private Transitions mTransitions;
- @Mock private SurfaceSession mSurfaceSession;
@Mock private IconProvider mIconProvider;
@Mock private WindowDecorViewModel mWindowDecorViewModel;
@Mock private ShellExecutor mMainExecutor;
@@ -116,8 +114,8 @@
@Mock private SplitScreen.SplitInvocationListener mInvocationListener;
private final TestShellExecutor mTestShellExecutor = new TestShellExecutor();
private SplitLayout mSplitLayout;
- private MainStage mMainStage;
- private SideStage mSideStage;
+ private StageTaskListener mMainStage;
+ private StageTaskListener mSideStage;
private StageCoordinator mStageCoordinator;
private SplitScreenTransitions mSplitScreenTransitions;
@@ -133,12 +131,12 @@
doReturn(mockExecutor).when(mTransitions).getAnimExecutor();
doReturn(mock(SurfaceControl.Transaction.class)).when(mTransactionPool).acquire();
mSplitLayout = SplitTestUtils.createMockSplitLayout();
- mMainStage = spy(new MainStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
- StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession,
+ mMainStage = spy(new StageTaskListener(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
+ StageTaskListener.StageListenerCallbacks.class), mSyncQueue,
mIconProvider, Optional.of(mWindowDecorViewModel)));
mMainStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
- mSideStage = spy(new SideStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
- StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession,
+ mSideStage = spy(new StageTaskListener(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
+ StageTaskListener.StageListenerCallbacks.class), mSyncQueue,
mIconProvider, Optional.of(mWindowDecorViewModel)));
mSideStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
mStageCoordinator = new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index 0054cb6..a6c16c4 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -50,7 +50,6 @@
import android.os.Handler;
import android.os.Looper;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
import android.window.RemoteTransition;
import android.window.WindowContainerTransaction;
@@ -97,9 +96,9 @@
@Mock
private SyncTransactionQueue mSyncQueue;
@Mock
- private MainStage mMainStage;
+ private StageTaskListener mMainStage;
@Mock
- private SideStage mSideStage;
+ private StageTaskListener mSideStage;
@Mock
private SplitLayout mSplitLayout;
@Mock
@@ -119,7 +118,6 @@
private final Rect mBounds2 = new Rect(5, 10, 15, 20);
private final Rect mRootBounds = new Rect(0, 0, 45, 60);
- private SurfaceSession mSurfaceSession = new SurfaceSession();
private SurfaceControl mRootLeash;
private SurfaceControl mDividerLeash;
private ActivityManager.RunningTaskInfo mRootTask;
@@ -139,7 +137,7 @@
mDisplayInsetsController, mSplitLayout, mTransitions, mTransactionPool,
mMainExecutor, mMainHandler, Optional.empty(), mLaunchAdjacentController,
Optional.empty()));
- mDividerLeash = new SurfaceControl.Builder(mSurfaceSession).setName("fakeDivider").build();
+ mDividerLeash = new SurfaceControl.Builder().setName("fakeDivider").build();
when(mSplitLayout.getBounds1()).thenReturn(mBounds1);
when(mSplitLayout.getBounds2()).thenReturn(mBounds2);
@@ -149,7 +147,7 @@
when(mSplitLayout.getDividerLeash()).thenReturn(mDividerLeash);
mRootTask = new TestRunningTaskInfoBuilder().build();
- mRootLeash = new SurfaceControl.Builder(mSurfaceSession).setName("test").build();
+ mRootLeash = new SurfaceControl.Builder().setName("test").build();
mStageCoordinator.onTaskAppeared(mRootTask, mRootLeash);
mSideStage.mRootTaskInfo = new TestRunningTaskInfoBuilder().build();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
index 946a7ef..b7b7d0d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
@@ -25,13 +25,13 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.app.ActivityManager;
import android.os.SystemProperties;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
import android.window.WindowContainerTransaction;
import androidx.test.annotation.UiThreadTest;
@@ -52,6 +52,7 @@
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
import java.util.Optional;
@@ -76,9 +77,10 @@
private IconProvider mIconProvider;
@Mock
private WindowDecorViewModel mWindowDecorViewModel;
+ @Spy
+ private WindowContainerTransaction mWct;
@Captor
private ArgumentCaptor<SyncTransactionQueue.TransactionRunnable> mRunnableCaptor;
- private SurfaceSession mSurfaceSession = new SurfaceSession();
private SurfaceControl mSurfaceControl;
private ActivityManager.RunningTaskInfo mRootTask;
private StageTaskListener mStageTaskListener;
@@ -93,12 +95,11 @@
DEFAULT_DISPLAY,
mCallbacks,
mSyncQueue,
- mSurfaceSession,
mIconProvider,
Optional.of(mWindowDecorViewModel));
mRootTask = new TestRunningTaskInfoBuilder().build();
mRootTask.parentTaskId = INVALID_TASK_ID;
- mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession).setName("test").build();
+ mSurfaceControl = new SurfaceControl.Builder().setName("test").build();
mStageTaskListener.onTaskAppeared(mRootTask, mSurfaceControl);
}
@@ -177,4 +178,31 @@
mStageTaskListener.evictAllChildren(wct);
assertFalse(wct.isEmpty());
}
+
+ @Test
+ public void testAddTask() {
+ final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
+ mStageTaskListener.addTask(task, mWct);
+
+ verify(mWct).reparent(eq(task.token), eq(mRootTask.token), eq(true));
+ }
+
+ @Test
+ public void testRemoveTask() {
+ final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
+ assertThat(mStageTaskListener.removeTask(task.taskId, null, mWct)).isFalse();
+
+ mStageTaskListener.mChildrenTaskInfo.put(task.taskId, task);
+ assertThat(mStageTaskListener.removeTask(task.taskId, null, mWct)).isTrue();
+ verify(mWct).reparent(eq(task.token), isNull(), eq(false));
+ }
+
+ @Test
+ public void testActiveDeactivate() {
+ mStageTaskListener.activate(mWct, true /* reparent */);
+ assertThat(mStageTaskListener.isActive()).isTrue();
+
+ mStageTaskListener.deactivate(mWct);
+ assertThat(mStageTaskListener.isActive()).isFalse();
+ }
}
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 c596ca3..17fd95b 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
@@ -49,7 +49,6 @@
import android.testing.TestableLooper;
import android.view.SurfaceControl;
import android.view.SurfaceHolder;
-import android.view.SurfaceSession;
import android.view.ViewTreeObserver;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
@@ -95,7 +94,6 @@
Looper mViewLooper;
TestHandler mViewHandler;
- SurfaceSession mSession;
SurfaceControl mLeash;
Context mContext;
@@ -106,7 +104,7 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mLeash = new SurfaceControl.Builder(mSession)
+ mLeash = new SurfaceControl.Builder()
.setName("test")
.build();
@@ -294,16 +292,6 @@
}
@Test
- public void testUnsetOnBackPressedOnTaskRoot_legacyTransitions() {
- assumeFalse(Transitions.ENABLE_SHELL_TRANSITIONS);
- mTaskViewTaskController.onTaskAppeared(mTaskInfo, mLeash);
- verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(true));
-
- mTaskViewTaskController.onTaskVanished(mTaskInfo);
- verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(false));
- }
-
- @Test
public void testOnNewTask_noSurface() {
assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
WindowContainerTransaction wct = new WindowContainerTransaction();
@@ -443,19 +431,6 @@
}
@Test
- public void testUnsetOnBackPressedOnTaskRoot() {
- assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
- WindowContainerTransaction wct = new WindowContainerTransaction();
- mTaskViewTaskController.prepareOpenAnimation(true /* newTask */,
- new SurfaceControl.Transaction(), new SurfaceControl.Transaction(), mTaskInfo,
- mLeash, wct);
- verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(true));
-
- mTaskViewTaskController.prepareCloseAnimation();
- verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(false));
- }
-
- @Test
public void testSetObscuredTouchRect() {
mTaskView.setObscuredTouchRect(
new Rect(/* left= */ 0, /* top= */ 10, /* right= */ 100, /* bottom= */ 120));
@@ -715,6 +690,16 @@
}
@Test
+ public void testOnAppeared_setsTrimmableTask() {
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ mTaskViewTaskController.prepareOpenAnimation(true /* newTask */,
+ new SurfaceControl.Transaction(), new SurfaceControl.Transaction(), mTaskInfo,
+ mLeash, wct);
+
+ assertThat(wct.getHierarchyOps().get(0).isTrimmableFromRecents()).isFalse();
+ }
+
+ @Test
public void testMoveToFullscreen_callsTaskRemovalStarted() {
WindowContainerTransaction wct = new WindowContainerTransaction();
mTaskViewTaskController.prepareOpenAnimation(true /* newTask */,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
index d2adae1..8f49de0 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
@@ -20,6 +20,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_PREPARE_BACK_NAVIGATION;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;
@@ -38,6 +39,10 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+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.view.SurfaceControl;
import android.window.TransitionInfo;
import android.window.TransitionInfo.TransitionMode;
@@ -46,6 +51,7 @@
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.window.flags.Flags;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestShellExecutor;
@@ -57,6 +63,7 @@
import com.android.wm.shell.sysui.ShellInit;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -70,6 +77,8 @@
@RunWith(AndroidJUnit4.class)
public class HomeTransitionObserverTest extends ShellTestCase {
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
private final ShellTaskOrganizer mOrganizer = mock(ShellTaskOrganizer.class);
private final TransactionPool mTransactionPool = mock(TransactionPool.class);
private final Context mContext =
@@ -187,6 +196,7 @@
}
@Test
+ @RequiresFlagsDisabled(Flags.FLAG_MIGRATE_PREDICTIVE_BACK_TRANSITION)
public void testHomeActivityWithBackGestureNotifiesHomeIsVisible() throws RemoteException {
TransitionInfo info = mock(TransitionInfo.class);
TransitionInfo.Change change = mock(TransitionInfo.Change.class);
@@ -205,6 +215,35 @@
verify(mListener, times(1)).onHomeVisibilityChanged(true);
}
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_MIGRATE_PREDICTIVE_BACK_TRANSITION)
+ public void testHomeActivityWithBackGestureNotifiesHomeIsVisibleAfterClose()
+ throws RemoteException {
+ TransitionInfo info = mock(TransitionInfo.class);
+ TransitionInfo.Change change = mock(TransitionInfo.Change.class);
+ ActivityManager.RunningTaskInfo taskInfo = mock(ActivityManager.RunningTaskInfo.class);
+ when(change.getTaskInfo()).thenReturn(taskInfo);
+ when(info.getChanges()).thenReturn(new ArrayList<>(List.of(change)));
+ when(info.getType()).thenReturn(TRANSIT_PREPARE_BACK_NAVIGATION);
+
+ when(change.hasFlags(FLAG_BACK_GESTURE_ANIMATED)).thenReturn(true);
+ setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_HOME, TRANSIT_OPEN, true);
+
+ mHomeTransitionObserver.onTransitionReady(mock(IBinder.class),
+ info,
+ mock(SurfaceControl.Transaction.class),
+ mock(SurfaceControl.Transaction.class));
+ verify(mListener, times(0)).onHomeVisibilityChanged(anyBoolean());
+
+ when(info.getType()).thenReturn(TRANSIT_TO_BACK);
+ setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_HOME, TRANSIT_CHANGE, true);
+ mHomeTransitionObserver.onTransitionReady(mock(IBinder.class),
+ info,
+ mock(SurfaceControl.Transaction.class),
+ mock(SurfaceControl.Transaction.class));
+ verify(mListener, times(1)).onHomeVisibilityChanged(true);
+ }
+
/**
* Helper class to initialize variables for the rest.
*/
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 be0549b..3dd8a2b 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
@@ -73,6 +73,7 @@
import com.android.wm.shell.TestRunningTaskInfoBuilder
import com.android.wm.shell.TestShellExecutor
import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser
+import com.android.wm.shell.apptoweb.AssistContentRequester
import com.android.wm.shell.common.DisplayChangeController
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.DisplayInsetsController
@@ -165,6 +166,7 @@
@Mock private lateinit var mockInteractionJankMonitor: InteractionJankMonitor
@Mock private lateinit var mockGenericLinksParser: AppToWebGenericLinksParser
@Mock private lateinit var mockUserHandle: UserHandle
+ @Mock private lateinit var mockAssistContentRequester: AssistContentRequester
@Mock private lateinit var mockToast: Toast
private val bgExecutor = TestShellExecutor()
@Mock private lateinit var mockMultiInstanceHelper: MultiInstanceHelper
@@ -218,6 +220,7 @@
mockTransitions,
Optional.of(mockDesktopTasksController),
mockGenericLinksParser,
+ mockAssistContentRequester,
mockMultiInstanceHelper,
mockDesktopModeWindowDecorFactory,
mockInputMonitorFactory,
@@ -1131,7 +1134,7 @@
whenever(
mockDesktopModeWindowDecorFactory.create(
any(), any(), any(), any(), any(), eq(task), any(), any(), any(), any(), any(),
- any(), any(), any())
+ any(), any(), any(), any())
).thenReturn(decoration)
decoration.mTaskInfo = task
whenever(decoration.isFocused).thenReturn(task.isFocused)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
index 596adfb..b9e542a0 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
@@ -46,6 +46,7 @@
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
+import android.app.assist.AssistContent;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -88,6 +89,7 @@
import com.android.wm.shell.TestRunningTaskInfoBuilder;
import com.android.wm.shell.TestShellExecutor;
import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser;
+import com.android.wm.shell.apptoweb.AssistContentRequester;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.MultiInstanceHelper;
import com.android.wm.shell.common.ShellExecutor;
@@ -133,6 +135,7 @@
private static final Uri TEST_URI1 = Uri.parse("https://www.google.com/");
private static final Uri TEST_URI2 = Uri.parse("https://docs.google.com/");
+ private static final Uri TEST_URI3 = Uri.parse("https://slides.google.com/");
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);
@@ -173,9 +176,14 @@
@Mock
private AppToWebGenericLinksParser mMockGenericLinksParser;
@Mock
+ private WindowManager mMockWindowManager;
+ @Mock
+ private AssistContentRequester mMockAssistContentRequester;
+ @Mock
private HandleMenu mMockHandleMenu;
@Mock
private HandleMenuFactory mMockHandleMenuFactory;
+ @Mock
private MultiInstanceHelper mMockMultiInstanceHelper;
@Captor
private ArgumentCaptor<Function1<Boolean, Unit>> mOnMaxMenuHoverChangeListener;
@@ -186,7 +194,8 @@
private SurfaceControl.Transaction mMockTransaction;
private StaticMockitoSession mMockitoSession;
private TestableContext mTestableContext;
- private ShellExecutor mBgExecutor = new TestShellExecutor();
+ private final ShellExecutor mBgExecutor = new TestShellExecutor();
+ private final AssistContent mAssistContent = new AssistContent();
/** Set up run before test class. */
@BeforeClass
@@ -220,9 +229,10 @@
final Display defaultDisplay = mock(Display.class);
doReturn(defaultDisplay).when(mMockDisplayController).getDisplay(Display.DEFAULT_DISPLAY);
doReturn(mInsetsState).when(mMockDisplayController).getInsetsState(anyInt());
- when(mMockHandleMenuFactory.create(any(), anyInt(), any(), any(),
+ when(mMockHandleMenuFactory.create(any(), any(), anyInt(), any(), any(),
any(), anyBoolean(), anyBoolean(), any(), anyInt(), anyInt(), anyInt()))
.thenReturn(mMockHandleMenu);
+ when(mMockMultiInstanceHelper.supportsMultiInstanceSplit(any())).thenReturn(false);
}
@After
@@ -385,6 +395,7 @@
}
@Test
+ @DisableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
public void updateRelayoutParams_fullscreen_inputChannelNotNeeded() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
@@ -401,6 +412,7 @@
}
@Test
+ @DisableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
public void updateRelayoutParams_multiwindow_inputChannelNotNeeded() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
@@ -491,7 +503,7 @@
.isTrue();
}
- @DisableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
+ @Test
public void relayout_fullscreenTask_appliesTransactionImmediately() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
@@ -518,7 +530,6 @@
}
@Test
- @DisableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
public void relayout_fullscreenTask_doesNotCreateViewHostImmediately() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
@@ -530,7 +541,6 @@
}
@Test
- @DisableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
public void relayout_fullscreenTask_postsViewHostCreation() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
@@ -559,7 +569,6 @@
}
@Test
- @DisableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
public void relayout_removesExistingHandlerCallback() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
@@ -574,7 +583,6 @@
}
@Test
- @DisableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
public void close_removesExistingHandlerCallback() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
@@ -671,10 +679,11 @@
public void capturedLink_handleMenuBrowserLinkSetToCapturedLinkIfValid() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(true /* visible */);
final DesktopModeWindowDecoration decor = createWindowDecoration(
- taskInfo, TEST_URI1 /* captured link */, TEST_URI2 /* generic link */);
+ taskInfo, TEST_URI1 /* captured link */, TEST_URI2 /* web uri */,
+ TEST_URI3 /* generic link */);
// Verify handle menu's browser link set as captured link
- decor.createHandleMenu(mMockSplitScreenController);
+ createHandleMenu(decor);
verifyHandleMenuCreated(TEST_URI1);
}
@@ -683,7 +692,8 @@
public void capturedLink_postsOnCapturedLinkExpiredRunnable() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(true /* visible */);
final DesktopModeWindowDecoration decor = createWindowDecoration(
- taskInfo, TEST_URI1 /* captured link */, null /* generic link */);
+ taskInfo, TEST_URI1 /* captured link */, null /* web uri */,
+ null /* generic link */);
final ArgumentCaptor<Runnable> runnableArgument = ArgumentCaptor.forClass(Runnable.class);
// Run runnable to set captured link to expired
@@ -692,7 +702,7 @@
// Verify captured link is no longer valid by verifying link is not set as handle menu
// browser link.
- decor.createHandleMenu(mMockSplitScreenController);
+ createHandleMenu(decor);
verifyHandleMenuCreated(null /* uri */);
}
@@ -701,7 +711,8 @@
public void capturedLink_capturedLinkNotResetToSameLink() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(true /* visible */);
final DesktopModeWindowDecoration decor = createWindowDecoration(
- taskInfo, TEST_URI1 /* captured link */, null /* generic link */);
+ taskInfo, TEST_URI1 /* captured link */, null /* web uri */,
+ null /* generic link */);
final ArgumentCaptor<Runnable> runnableArgument = ArgumentCaptor.forClass(Runnable.class);
// Run runnable to set captured link to expired
@@ -712,7 +723,7 @@
decor.relayout(taskInfo);
// Verify handle menu's browser link not set to captured link since link is expired
- decor.createHandleMenu(mMockSplitScreenController);
+ createHandleMenu(decor);
verifyHandleMenuCreated(null /* uri */);
}
@@ -721,11 +732,12 @@
public void capturedLink_capturedLinkStillUsedIfExpiredAfterHandleMenuCreation() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(true /* visible */);
final DesktopModeWindowDecoration decor = createWindowDecoration(
- taskInfo, TEST_URI1 /* captured link */, null /* generic link */);
+ taskInfo, TEST_URI1 /* captured link */, null /* web uri */,
+ null /* generic link */);
final ArgumentCaptor<Runnable> runnableArgument = ArgumentCaptor.forClass(Runnable.class);
// Create handle menu before link expires
- decor.createHandleMenu(mMockSplitScreenController);
+ createHandleMenu(decor);
// Run runnable to set captured link to expired
verify(mMockHandler).postDelayed(runnableArgument.capture(), anyLong());
@@ -733,7 +745,7 @@
// Verify handle menu's browser link is set to captured link since menu was opened before
// captured link expired
- decor.createHandleMenu(mMockSplitScreenController);
+ createHandleMenu(decor);
verifyHandleMenuCreated(TEST_URI1);
}
@@ -742,12 +754,13 @@
public void capturedLink_capturedLinkExpiresAfterClick() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(true /* visible */);
final DesktopModeWindowDecoration decor = createWindowDecoration(
- taskInfo, TEST_URI1 /* captured link */, null /* generic link */);
+ taskInfo, TEST_URI1 /* captured link */, null /* web uri */,
+ null /* generic link */);
final ArgumentCaptor<Function1<Uri, Unit>> openInBrowserCaptor =
ArgumentCaptor.forClass(Function1.class);
// Simulate menu opening and clicking open in browser button
- decor.createHandleMenu(mMockSplitScreenController);
+ createHandleMenu(decor);
verify(mMockHandleMenu).show(
any(),
any(),
@@ -761,7 +774,7 @@
// Verify handle menu's browser link not set to captured link since link not valid after
// open in browser clicked
- decor.createHandleMenu(mMockSplitScreenController);
+ createHandleMenu(decor);
verifyHandleMenuCreated(null /* uri */);
}
@@ -770,10 +783,11 @@
public void capturedLink_openInBrowserListenerCalledOnClick() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(true /* visible */);
final DesktopModeWindowDecoration decor = createWindowDecoration(
- taskInfo, TEST_URI1 /* captured link */, null /* generic link */);
+ taskInfo, TEST_URI1 /* captured link */, null /* web uri */,
+ null /* generic link */);
final ArgumentCaptor<Function1<Uri, Unit>> openInBrowserCaptor =
ArgumentCaptor.forClass(Function1.class);
- decor.createHandleMenu(mMockSplitScreenController);
+ createHandleMenu(decor);
verify(mMockHandleMenu).show(
any(),
any(),
@@ -791,24 +805,38 @@
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_TO_WEB)
- public void genericLink_genericLinkUsedWhenCapturedLinkUnavailable() {
+ public void webUriLink_webUriLinkUsedWhenCapturedLinkUnavailable() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(true /* visible */);
final DesktopModeWindowDecoration decor = createWindowDecoration(
- taskInfo, null /* captured link */, TEST_URI2 /* generic link */);
-
- // Verify handle menu's browser link set as generic link no captured link is available
- decor.createHandleMenu(mMockSplitScreenController);
+ taskInfo, null /* captured link */, TEST_URI2 /* web uri */,
+ TEST_URI3 /* generic link */);
+ // Verify handle menu's browser link set as web uri link when captured link is unavailable
+ createHandleMenu(decor);
verifyHandleMenuCreated(TEST_URI2);
}
@Test
+ @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_APP_TO_WEB)
+ public void genericLink_genericLinkUsedWhenCapturedLinkAndWebUriUnavailable() {
+ final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(true /* visible */);
+ final DesktopModeWindowDecoration decor = createWindowDecoration(
+ taskInfo, null /* captured link */, null /* web uri */,
+ TEST_URI3 /* generic link */);
+
+ // Verify handle menu's browser link set as generic link when captured link and web uri link
+ // are unavailable
+ createHandleMenu(decor);
+ verifyHandleMenuCreated(TEST_URI3);
+ }
+
+ @Test
public void handleMenu_onCloseMenuClick_closesMenu() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
final DesktopModeWindowDecoration decoration = createWindowDecoration(taskInfo,
true /* relayout */);
final ArgumentCaptor<Function0<Unit>> closeClickListener =
ArgumentCaptor.forClass(Function0.class);
- decoration.createHandleMenu(mMockSplitScreenController);
+ createHandleMenu(decoration);
verify(mMockHandleMenu).show(
any(),
any(),
@@ -826,7 +854,7 @@
}
private void verifyHandleMenuCreated(@Nullable Uri uri) {
- verify(mMockHandleMenuFactory).create(any(), anyInt(), any(), any(),
+ verify(mMockHandleMenuFactory).create(any(), any(), anyInt(), any(), any(),
any(), anyBoolean(), anyBoolean(), eq(uri), anyInt(), anyInt(), anyInt());
}
@@ -858,9 +886,10 @@
private DesktopModeWindowDecoration createWindowDecoration(
ActivityManager.RunningTaskInfo taskInfo, @Nullable Uri capturedLink,
- @Nullable Uri genericLink) {
+ @Nullable Uri webUri, @Nullable Uri genericLink) {
taskInfo.capturedLink = capturedLink;
taskInfo.capturedLinkTimestamp = System.currentTimeMillis();
+ mAssistContent.setWebUri(webUri);
final String genericLinkString = genericLink == null ? null : genericLink.toString();
doReturn(genericLinkString).when(mMockGenericLinksParser).getGenericLink(any());
// Relayout to set captured link
@@ -892,10 +921,10 @@
mContext, mMockDisplayController, mMockSplitScreenController,
mMockShellTaskOrganizer, taskInfo, mMockSurfaceControl, mMockHandler, mBgExecutor,
mMockChoreographer, mMockSyncQueue, mMockRootTaskDisplayAreaOrganizer,
- mMockGenericLinksParser, SurfaceControl.Builder::new, mMockTransactionSupplier,
- WindowContainerTransaction::new, SurfaceControl::new,
- mMockSurfaceControlViewHostFactory, maximizeMenuFactory, mMockHandleMenuFactory,
- mMockMultiInstanceHelper);
+ mMockGenericLinksParser, mMockAssistContentRequester, SurfaceControl.Builder::new,
+ mMockTransactionSupplier, WindowContainerTransaction::new, SurfaceControl::new,
+ new WindowManagerWrapper(mMockWindowManager), mMockSurfaceControlViewHostFactory,
+ maximizeMenuFactory, mMockHandleMenuFactory, mMockMultiInstanceHelper);
windowDecor.setCaptionListeners(mMockTouchEventListener, mMockTouchEventListener,
mMockTouchEventListener, mMockTouchEventListener);
windowDecor.setExclusionRegionListener(mMockExclusionRegionListener);
@@ -923,6 +952,13 @@
}
+ private void createHandleMenu(@NonNull DesktopModeWindowDecoration decor) {
+ decor.createHandleMenu();
+ // Call DesktopModeWindowDecoration#onAssistContentReceived because decor waits to receive
+ // {@link AssistContent} before creating the menu
+ decor.onAssistContentReceived(mAssistContent);
+ }
+
private static boolean hasNoInputChannelFeature(RelayoutParams params) {
return (params.mInputFeatures & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL)
!= 0;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt
index 627dfe7..100abbb 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt
@@ -33,6 +33,7 @@
import android.view.SurfaceControl
import android.view.SurfaceControlViewHost
import android.view.View
+import android.view.WindowManager
import androidx.core.graphics.toPointF
import androidx.test.filters.SmallTest
import com.android.window.flags.Flags
@@ -77,6 +78,8 @@
@Mock
private lateinit var mockDesktopWindowDecoration: DesktopModeWindowDecoration
@Mock
+ private lateinit var mockWindowManager: WindowManager
+ @Mock
private lateinit var onClickListener: View.OnClickListener
@Mock
private lateinit var onTouchListener: View.OnTouchListener
@@ -230,8 +233,9 @@
}
else -> error("Invalid windowing mode")
}
- val handleMenu = HandleMenu(mockDesktopWindowDecoration, layoutId, appIcon, appName,
- splitScreenController, shouldShowWindowingPill = true,
+ val handleMenu = HandleMenu(mockDesktopWindowDecoration,
+ WindowManagerWrapper(mockWindowManager),
+ layoutId, appIcon, appName, splitScreenController, shouldShowWindowingPill = true,
shouldShowNewWindowButton = true,
null /* openInBrowserLink */, captionWidth = HANDLE_WIDTH, captionHeight = 50,
captionX = captionX
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/ResizeVeilTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/ResizeVeilTest.kt
index a07be79..e0d16aa 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/ResizeVeilTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/ResizeVeilTest.kt
@@ -97,7 +97,7 @@
.thenReturn(spyResizeVeilSurfaceBuilder)
doReturn(mockResizeVeilSurface).whenever(spyResizeVeilSurfaceBuilder).build()
whenever(mockSurfaceControlBuilderFactory
- .create(eq("Resize veil background of Task=" + taskInfo.taskId), any()))
+ .create(eq("Resize veil background of Task=" + taskInfo.taskId)))
.thenReturn(spyBackgroundSurfaceBuilder)
doReturn(mockBackgroundSurface).whenever(spyBackgroundSurfaceBuilder).build()
whenever(mockSurfaceControlBuilderFactory
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainerTest.kt
index 28b4eb6..0f52ed7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainerTest.kt
@@ -25,6 +25,7 @@
import androidx.test.filters.SmallTest
import com.android.wm.shell.R
import com.android.wm.shell.ShellTestCase
+import com.android.wm.shell.windowdecor.WindowManagerWrapper
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -70,6 +71,7 @@
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
viewContainer = AdditionalSystemViewContainer(
mockContext,
+ WindowManagerWrapper(mockWindowManager),
TASK_ID,
X,
Y,
diff --git a/libs/hostgraphics/Android.bp b/libs/hostgraphics/Android.bp
index 09232b6..a58493a 100644
--- a/libs/hostgraphics/Android.bp
+++ b/libs/hostgraphics/Android.bp
@@ -7,6 +7,17 @@
default_applicable_licenses: ["frameworks_base_license"],
}
+cc_library_headers {
+ name: "libhostgraphics_headers",
+ host_supported: true,
+ export_include_dirs: ["include"],
+ target: {
+ windows: {
+ enabled: true,
+ },
+ },
+}
+
cc_library_host_static {
name: "libhostgraphics",
@@ -30,12 +41,13 @@
],
header_libs: [
+ "libhostgraphics_headers",
"libnativebase_headers",
"libnativedisplay_headers",
"libnativewindow_headers",
],
- export_include_dirs: ["."],
+ export_include_dirs: ["include"],
target: {
windows: {
diff --git a/libs/hostgraphics/gui/BufferItem.h b/libs/hostgraphics/include/gui/BufferItem.h
similarity index 100%
rename from libs/hostgraphics/gui/BufferItem.h
rename to libs/hostgraphics/include/gui/BufferItem.h
diff --git a/libs/hostgraphics/gui/BufferItemConsumer.h b/libs/hostgraphics/include/gui/BufferItemConsumer.h
similarity index 100%
rename from libs/hostgraphics/gui/BufferItemConsumer.h
rename to libs/hostgraphics/include/gui/BufferItemConsumer.h
diff --git a/libs/hostgraphics/gui/BufferQueue.h b/libs/hostgraphics/include/gui/BufferQueue.h
similarity index 100%
rename from libs/hostgraphics/gui/BufferQueue.h
rename to libs/hostgraphics/include/gui/BufferQueue.h
diff --git a/libs/hostgraphics/gui/ConsumerBase.h b/libs/hostgraphics/include/gui/ConsumerBase.h
similarity index 100%
rename from libs/hostgraphics/gui/ConsumerBase.h
rename to libs/hostgraphics/include/gui/ConsumerBase.h
diff --git a/libs/hostgraphics/gui/IGraphicBufferConsumer.h b/libs/hostgraphics/include/gui/IGraphicBufferConsumer.h
similarity index 100%
rename from libs/hostgraphics/gui/IGraphicBufferConsumer.h
rename to libs/hostgraphics/include/gui/IGraphicBufferConsumer.h
diff --git a/libs/hostgraphics/gui/IGraphicBufferProducer.h b/libs/hostgraphics/include/gui/IGraphicBufferProducer.h
similarity index 100%
rename from libs/hostgraphics/gui/IGraphicBufferProducer.h
rename to libs/hostgraphics/include/gui/IGraphicBufferProducer.h
diff --git a/libs/hostgraphics/gui/Surface.h b/libs/hostgraphics/include/gui/Surface.h
similarity index 100%
rename from libs/hostgraphics/gui/Surface.h
rename to libs/hostgraphics/include/gui/Surface.h
diff --git a/libs/hostgraphics/ui/Fence.h b/libs/hostgraphics/include/ui/Fence.h
similarity index 100%
rename from libs/hostgraphics/ui/Fence.h
rename to libs/hostgraphics/include/ui/Fence.h
diff --git a/libs/hostgraphics/ui/GraphicBuffer.h b/libs/hostgraphics/include/ui/GraphicBuffer.h
similarity index 100%
rename from libs/hostgraphics/ui/GraphicBuffer.h
rename to libs/hostgraphics/include/ui/GraphicBuffer.h
diff --git a/libs/hwui/AutoBackendTextureRelease.cpp b/libs/hwui/AutoBackendTextureRelease.cpp
index 5f5ffe9..27add35 100644
--- a/libs/hwui/AutoBackendTextureRelease.cpp
+++ b/libs/hwui/AutoBackendTextureRelease.cpp
@@ -17,11 +17,12 @@
#include "AutoBackendTextureRelease.h"
#include <SkImage.h>
-#include <include/gpu/ganesh/SkImageGanesh.h>
-#include <include/gpu/GrDirectContext.h>
-#include <include/gpu/GrBackendSurface.h>
#include <include/gpu/MutableTextureState.h>
+#include <include/gpu/ganesh/GrBackendSurface.h>
+#include <include/gpu/ganesh/GrDirectContext.h>
+#include <include/gpu/ganesh/SkImageGanesh.h>
#include <include/gpu/vk/VulkanMutableTextureState.h>
+
#include "renderthread/RenderThread.h"
#include "utils/Color.h"
#include "utils/PaintUtils.h"
diff --git a/libs/hwui/AutoBackendTextureRelease.h b/libs/hwui/AutoBackendTextureRelease.h
index f0eb2a8..d58cd17 100644
--- a/libs/hwui/AutoBackendTextureRelease.h
+++ b/libs/hwui/AutoBackendTextureRelease.h
@@ -16,10 +16,10 @@
#pragma once
-#include <GrAHardwareBufferUtils.h>
-#include <GrBackendSurface.h>
#include <SkImage.h>
#include <android/hardware_buffer.h>
+#include <include/android/GrAHardwareBufferUtils.h>
+#include <include/gpu/ganesh/GrBackendSurface.h>
#include <system/graphics.h>
namespace android {
diff --git a/libs/hwui/FeatureFlags.h b/libs/hwui/FeatureFlags.h
index c1c30f5..c0cedf1 100644
--- a/libs/hwui/FeatureFlags.h
+++ b/libs/hwui/FeatureFlags.h
@@ -25,14 +25,6 @@
namespace text_feature {
-inline bool fix_double_underline() {
-#ifdef __ANDROID__
- return com_android_text_flags_fix_double_underline();
-#else
- return true;
-#endif // __ANDROID__
-}
-
inline bool deprecate_ui_fonts() {
#ifdef __ANDROID__
return com_android_text_flags_deprecate_ui_fonts();
diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp
index 27ea150..236c3736 100644
--- a/libs/hwui/HardwareBitmapUploader.cpp
+++ b/libs/hwui/HardwareBitmapUploader.cpp
@@ -21,8 +21,6 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <GLES3/gl3.h>
-#include <GrDirectContext.h>
-#include <GrTypes.h>
#include <SkBitmap.h>
#include <SkCanvas.h>
#include <SkImage.h>
@@ -30,6 +28,8 @@
#include <SkImageInfo.h>
#include <SkRefCnt.h>
#include <gui/TraceUtils.h>
+#include <include/gpu/ganesh/GrDirectContext.h>
+#include <include/gpu/ganesh/GrTypes.h>
#include <utils/GLUtils.h>
#include <utils/NdkUtils.h>
#include <utils/Trace.h>
@@ -318,6 +318,11 @@
return has101012Support;
}
+bool HardwareBitmapUploader::has10101010Support() {
+ static bool has1010110Support = checkSupport(AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM);
+ return has1010110Support;
+}
+
bool HardwareBitmapUploader::hasAlpha8Support() {
static bool hasAlpha8Support = checkSupport(AHARDWAREBUFFER_FORMAT_R8_UNORM);
return hasAlpha8Support;
@@ -376,6 +381,19 @@
}
formatInfo.format = GL_RGBA;
break;
+ case kRGBA_10x6_SkColorType:
+ formatInfo.isSupported = HardwareBitmapUploader::has10101010Support();
+ if (formatInfo.isSupported) {
+ formatInfo.type = 0; // Not supported in GL
+ formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM;
+ formatInfo.vkFormat = VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16;
+ } else {
+ formatInfo.type = GL_UNSIGNED_BYTE;
+ formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
+ formatInfo.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
+ }
+ formatInfo.format = 0; // Not supported in GL
+ break;
case kAlpha_8_SkColorType:
formatInfo.isSupported = HardwareBitmapUploader::hasAlpha8Support();
if (formatInfo.isSupported) {
diff --git a/libs/hwui/HardwareBitmapUploader.h b/libs/hwui/HardwareBitmapUploader.h
index 00ee996..76cb80b 100644
--- a/libs/hwui/HardwareBitmapUploader.h
+++ b/libs/hwui/HardwareBitmapUploader.h
@@ -33,12 +33,14 @@
#ifdef __ANDROID__
static bool hasFP16Support();
static bool has1010102Support();
+ static bool has10101010Support();
static bool hasAlpha8Support();
#else
static bool hasFP16Support() {
return true;
}
static bool has1010102Support() { return true; }
+ static bool has10101010Support() { return true; }
static bool hasAlpha8Support() { return true; }
#endif
};
diff --git a/libs/hwui/Mesh.h b/libs/hwui/Mesh.h
index 8c6ca97..afc6adf 100644
--- a/libs/hwui/Mesh.h
+++ b/libs/hwui/Mesh.h
@@ -17,8 +17,8 @@
#ifndef MESH_H_
#define MESH_H_
-#include <GrDirectContext.h>
#include <SkMesh.h>
+#include <include/gpu/ganesh/GrDirectContext.h>
#include <include/gpu/ganesh/SkMeshGanesh.h>
#include <jni.h>
#include <log/log.h>
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index d026379..60d7f2d 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -16,9 +16,12 @@
#include "RecordingCanvas.h"
-#include <GrRecordingContext.h>
#include <SkMesh.h>
#include <hwui/Paint.h>
+#include <include/gpu/GpuTypes.h>
+#include <include/gpu/ganesh/GrDirectContext.h>
+#include <include/gpu/ganesh/GrRecordingContext.h>
+#include <include/gpu/ganesh/SkMeshGanesh.h>
#include <log/log.h>
#include <experimental/type_traits>
@@ -48,9 +51,6 @@
#include "Tonemapper.h"
#include "VectorDrawable.h"
#include "effects/GainmapRenderer.h"
-#include "include/gpu/GpuTypes.h" // from Skia
-#include "include/gpu/GrDirectContext.h"
-#include "include/gpu/ganesh/SkMeshGanesh.h"
#include "pipeline/skia/AnimatedDrawables.h"
#include "pipeline/skia/FunctorDrawable.h"
#ifdef __ANDROID__
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 72e83af..9e825fb 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -841,9 +841,6 @@
sk_sp<SkTextBlob> textBlob(builder.make());
applyLooper(&paintCopy, [&](const SkPaint& p) { mCanvas->drawTextBlob(textBlob, 0, 0, p); });
- if (!text_feature::fix_double_underline()) {
- drawTextDecorations(x, y, totalAdvance, paintCopy);
- }
}
void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset,
diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp
index 80b6c03..5af4af2 100644
--- a/libs/hwui/hwui/Canvas.cpp
+++ b/libs/hwui/hwui/Canvas.cpp
@@ -110,28 +110,26 @@
DrawTextFunctor f(layout, this, paint, x, y, layout.getAdvance());
MinikinUtils::forFontRun(layout, &paint, f);
- if (text_feature::fix_double_underline()) {
- Paint copied(paint);
- PaintFilter* filter = getPaintFilter();
- if (filter != nullptr) {
- filter->filterFullPaint(&copied);
+ Paint copied(paint);
+ PaintFilter* filter = getPaintFilter();
+ if (filter != nullptr) {
+ filter->filterFullPaint(&copied);
+ }
+ const bool isUnderline = copied.isUnderline();
+ const bool isStrikeThru = copied.isStrikeThru();
+ if (isUnderline || isStrikeThru) {
+ const SkScalar left = x;
+ const SkScalar right = x + layout.getAdvance();
+ if (isUnderline) {
+ const SkScalar top = y + f.getUnderlinePosition();
+ drawStroke(left, right, top, f.getUnderlineThickness(), copied, this);
}
- const bool isUnderline = copied.isUnderline();
- const bool isStrikeThru = copied.isStrikeThru();
- if (isUnderline || isStrikeThru) {
- const SkScalar left = x;
- const SkScalar right = x + layout.getAdvance();
- if (isUnderline) {
- const SkScalar top = y + f.getUnderlinePosition();
- drawStroke(left, right, top, f.getUnderlineThickness(), copied, this);
- }
- if (isStrikeThru) {
- float textSize = paint.getSkFont().getSize();
- const float position = textSize * Paint::kStdStrikeThru_Top;
- const SkScalar thickness = textSize * Paint::kStdStrikeThru_Thickness;
- const SkScalar top = y + position;
- drawStroke(left, right, top, thickness, copied, this);
- }
+ if (isStrikeThru) {
+ float textSize = paint.getSkFont().getSize();
+ const float position = textSize * Paint::kStdStrikeThru_Top;
+ const SkScalar thickness = textSize * Paint::kStdStrikeThru_Thickness;
+ const SkScalar top = y + position;
+ drawStroke(left, right, top, thickness, copied, this);
}
}
}
diff --git a/libs/hwui/hwui/DrawTextFunctor.h b/libs/hwui/hwui/DrawTextFunctor.h
index 0efb2c8..d7bf201 100644
--- a/libs/hwui/hwui/DrawTextFunctor.h
+++ b/libs/hwui/hwui/DrawTextFunctor.h
@@ -142,32 +142,30 @@
canvas->drawGlyphs(glyphFunc, glyphCount, paint, x, y, totalAdvance);
}
- if (text_feature::fix_double_underline()) {
- // Extract underline position and thickness.
- if (paint.isUnderline()) {
- SkFontMetrics metrics;
- paint.getSkFont().getMetrics(&metrics);
- const float textSize = paint.getSkFont().getSize();
- SkScalar position;
- if (!metrics.hasUnderlinePosition(&position)) {
- position = textSize * Paint::kStdUnderline_Top;
- }
- SkScalar thickness;
- if (!metrics.hasUnderlineThickness(&thickness)) {
- thickness = textSize * Paint::kStdUnderline_Thickness;
- }
-
- // If multiple fonts are used, use the most bottom position and most thick stroke
- // width as the underline position. This follows the CSS standard:
- // https://www.w3.org/TR/css-text-decor-3/#text-underline-position-property
- // <quote>
- // The exact position and thickness of line decorations is UA-defined in this level.
- // However, for underlines and overlines the UA must use a single thickness and
- // position on each line for the decorations deriving from a single decorating box.
- // </quote>
- underlinePosition = std::max(underlinePosition, position);
- underlineThickness = std::max(underlineThickness, thickness);
+ // Extract underline position and thickness.
+ if (paint.isUnderline()) {
+ SkFontMetrics metrics;
+ paint.getSkFont().getMetrics(&metrics);
+ const float textSize = paint.getSkFont().getSize();
+ SkScalar position;
+ if (!metrics.hasUnderlinePosition(&position)) {
+ position = textSize * Paint::kStdUnderline_Top;
}
+ SkScalar thickness;
+ if (!metrics.hasUnderlineThickness(&thickness)) {
+ thickness = textSize * Paint::kStdUnderline_Thickness;
+ }
+
+ // If multiple fonts are used, use the most bottom position and most thick stroke
+ // width as the underline position. This follows the CSS standard:
+ // https://www.w3.org/TR/css-text-decor-3/#text-underline-position-property
+ // <quote>
+ // The exact position and thickness of line decorations is UA-defined in this level.
+ // However, for underlines and overlines the UA must use a single thickness and
+ // position on each line for the decorations deriving from a single decorating box.
+ // </quote>
+ underlinePosition = std::max(underlinePosition, position);
+ underlineThickness = std::max(underlineThickness, thickness);
}
}
diff --git a/libs/hwui/pipeline/skia/ATraceMemoryDump.cpp b/libs/hwui/pipeline/skia/ATraceMemoryDump.cpp
index 756b937..3800645 100644
--- a/libs/hwui/pipeline/skia/ATraceMemoryDump.cpp
+++ b/libs/hwui/pipeline/skia/ATraceMemoryDump.cpp
@@ -16,12 +16,11 @@
#include "ATraceMemoryDump.h"
+#include <include/gpu/ganesh/GrDirectContext.h>
#include <utils/Trace.h>
#include <cstring>
-#include "GrDirectContext.h"
-
namespace android {
namespace uirenderer {
namespace skiapipeline {
diff --git a/libs/hwui/pipeline/skia/ATraceMemoryDump.h b/libs/hwui/pipeline/skia/ATraceMemoryDump.h
index 777d1a2..86ff33f 100644
--- a/libs/hwui/pipeline/skia/ATraceMemoryDump.h
+++ b/libs/hwui/pipeline/skia/ATraceMemoryDump.h
@@ -16,9 +16,9 @@
#pragma once
-#include <GrDirectContext.h>
#include <SkString.h>
#include <SkTraceMemoryDump.h>
+#include <include/gpu/ganesh/GrDirectContext.h>
#include <string>
#include <unordered_map>
diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
index 5d3fb30..85432bf 100644
--- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
@@ -15,24 +15,26 @@
*/
#include "GLFunctorDrawable.h"
-#include <GrDirectContext.h>
+
+#include <effects/GainmapRenderer.h>
+#include <include/gpu/GpuTypes.h>
+#include <include/gpu/ganesh/GrBackendSurface.h>
+#include <include/gpu/ganesh/GrDirectContext.h>
+#include <include/gpu/ganesh/SkSurfaceGanesh.h>
+#include <include/gpu/ganesh/gl/GrGLBackendSurface.h>
+#include <include/gpu/ganesh/gl/GrGLTypes.h>
#include <private/hwui/DrawGlInfo.h>
+
#include "FunctorDrawable.h"
-#include "GrBackendSurface.h"
#include "RenderNode.h"
#include "SkAndroidFrameworkUtils.h"
#include "SkCanvas.h"
#include "SkCanvasAndroid.h"
#include "SkClipStack.h"
-#include "SkRect.h"
#include "SkM44.h"
-#include <include/gpu/ganesh/SkSurfaceGanesh.h>
-#include "include/gpu/GpuTypes.h" // from Skia
-#include <include/gpu/gl/GrGLTypes.h>
-#include <include/gpu/ganesh/gl/GrGLBackendSurface.h>
-#include "utils/GLUtils.h"
-#include <effects/GainmapRenderer.h>
+#include "SkRect.h"
#include "renderthread/CanvasContext.h"
+#include "utils/GLUtils.h"
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index 99f54c1..8f3366c 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -16,17 +16,17 @@
#include "LayerDrawable.h"
+#include <include/gpu/ganesh/GrBackendSurface.h>
+#include <include/gpu/ganesh/gl/GrGLTypes.h>
#include <shaders/shaders.h>
#include <utils/Color.h>
#include <utils/MathUtils.h>
#include "DeviceInfo.h"
-#include "GrBackendSurface.h"
#include "SkColorFilter.h"
#include "SkRuntimeEffect.h"
#include "SkSurface.h"
#include "Tonemapper.h"
-#include "gl/GrGLTypes.h"
#include "math/mat4.h"
#include "system/graphics-base-v1.0.h"
#include "system/window.h"
diff --git a/libs/hwui/pipeline/skia/ShaderCache.cpp b/libs/hwui/pipeline/skia/ShaderCache.cpp
index 8e07a2f..22f59a6 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.cpp
+++ b/libs/hwui/pipeline/skia/ShaderCache.cpp
@@ -16,9 +16,9 @@
#include "ShaderCache.h"
-#include <GrDirectContext.h>
#include <SkData.h>
#include <gui/TraceUtils.h>
+#include <include/gpu/ganesh/GrDirectContext.h>
#include <log/log.h>
#include <openssl/sha.h>
diff --git a/libs/hwui/pipeline/skia/ShaderCache.h b/libs/hwui/pipeline/skia/ShaderCache.h
index 40dfc9d..4c01161 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.h
+++ b/libs/hwui/pipeline/skia/ShaderCache.h
@@ -17,10 +17,10 @@
#pragma once
#include <FileBlobCache.h>
-#include <GrContextOptions.h>
#include <SkRefCnt.h>
#include <cutils/compiler.h>
#include <ftl/shared_mutex.h>
+#include <include/gpu/ganesh/GrContextOptions.h>
#include <utils/Mutex.h>
#include <memory>
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index e4b1f91..0768f45 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -16,14 +16,14 @@
#include "pipeline/skia/SkiaOpenGLPipeline.h"
-#include <GrBackendSurface.h>
#include <SkBlendMode.h>
#include <SkImageInfo.h>
#include <cutils/properties.h>
#include <gui/TraceUtils.h>
+#include <include/gpu/ganesh/GrBackendSurface.h>
#include <include/gpu/ganesh/SkSurfaceGanesh.h>
#include <include/gpu/ganesh/gl/GrGLBackendSurface.h>
-#include <include/gpu/gl/GrGLTypes.h>
+#include <include/gpu/ganesh/gl/GrGLTypes.h>
#include <strings.h>
#include "DeferredLayerUpdater.h"
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index d06dba0..e1de1e6 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -16,14 +16,14 @@
#include "pipeline/skia/SkiaVulkanPipeline.h"
-#include <GrDirectContext.h>
-#include <GrTypes.h>
#include <SkSurface.h>
#include <SkTypes.h>
#include <cutils/properties.h>
#include <gui/TraceUtils.h>
+#include <include/gpu/ganesh/GrDirectContext.h>
+#include <include/gpu/ganesh/GrTypes.h>
+#include <include/gpu/ganesh/vk/GrVkTypes.h>
#include <strings.h>
-#include <vk/GrVkTypes.h>
#include "DeferredLayerUpdater.h"
#include "LightingInfo.h"
diff --git a/libs/hwui/pipeline/skia/StretchMask.h b/libs/hwui/pipeline/skia/StretchMask.h
index dc698b8..0baed9f 100644
--- a/libs/hwui/pipeline/skia/StretchMask.h
+++ b/libs/hwui/pipeline/skia/StretchMask.h
@@ -15,9 +15,10 @@
*/
#pragma once
-#include "GrRecordingContext.h"
-#include <effects/StretchEffect.h>
#include <SkSurface.h>
+#include <effects/StretchEffect.h>
+#include <include/gpu/ganesh/GrRecordingContext.h>
+
#include "SkiaDisplayList.h"
namespace android::uirenderer {
diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
index 21fe6ff..1ebc3c8 100644
--- a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
@@ -19,12 +19,12 @@
#include <SkAndroidFrameworkUtils.h>
#include <SkImage.h>
#include <SkM44.h>
-#include <include/gpu/ganesh/vk/GrBackendDrawableInfo.h>
#include <gui/TraceUtils.h>
+#include <include/gpu/ganesh/vk/GrBackendDrawableInfo.h>
+#include <include/gpu/ganesh/vk/GrVkTypes.h>
#include <private/hwui/DrawVkInfo.h>
#include <utils/Color.h>
#include <utils/Trace.h>
-#include <vk/GrVkTypes.h>
#include <thread>
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index ac2a936..2771780 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -16,10 +16,10 @@
#include "CacheManager.h"
-#include <GrContextOptions.h>
-#include <GrTypes.h>
#include <SkExecutor.h>
#include <SkGraphics.h>
+#include <include/gpu/ganesh/GrContextOptions.h>
+#include <include/gpu/ganesh/GrTypes.h>
#include <math.h>
#include <utils/Trace.h>
diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h
index bcfa4f3..94f1005 100644
--- a/libs/hwui/renderthread/CacheManager.h
+++ b/libs/hwui/renderthread/CacheManager.h
@@ -18,7 +18,7 @@
#define CACHEMANAGER_H
#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
-#include <GrDirectContext.h>
+#include <include/gpu/ganesh/GrDirectContext.h>
#endif
#include <SkSurface.h>
#include <utils/String8.h>
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index a024aeb..92c6ad1 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -16,12 +16,12 @@
#include "RenderThread.h"
-#include <GrContextOptions.h>
#include <android-base/properties.h>
#include <dlfcn.h>
-#include <gl/GrGLInterface.h>
#include <gui/TraceUtils.h>
+#include <include/gpu/ganesh/GrContextOptions.h>
#include <include/gpu/ganesh/gl/GrGLDirectContext.h>
+#include <include/gpu/ganesh/gl/GrGLInterface.h>
#include <private/android/choreographer.h>
#include <sys/resource.h>
#include <ui/FatVector.h>
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 045d26f..86fddba 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -17,9 +17,9 @@
#ifndef RENDERTHREAD_H_
#define RENDERTHREAD_H_
-#include <GrDirectContext.h>
#include <SkBitmap.h>
#include <cutils/compiler.h>
+#include <include/gpu/ganesh/GrDirectContext.h>
#include <surface_control_private.h>
#include <utils/Thread.h>
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 4d185c6..e302393 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -18,19 +18,19 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include <GrBackendSemaphore.h>
-#include <GrBackendSurface.h>
-#include <GrDirectContext.h>
-#include <GrTypes.h>
#include <android/sync.h>
#include <gui/TraceUtils.h>
+#include <include/gpu/ganesh/GrBackendSemaphore.h>
+#include <include/gpu/ganesh/GrBackendSurface.h>
+#include <include/gpu/ganesh/GrDirectContext.h>
+#include <include/gpu/ganesh/GrTypes.h>
#include <include/gpu/ganesh/SkSurfaceGanesh.h>
#include <include/gpu/ganesh/vk/GrVkBackendSemaphore.h>
#include <include/gpu/ganesh/vk/GrVkBackendSurface.h>
#include <include/gpu/ganesh/vk/GrVkDirectContext.h>
+#include <include/gpu/ganesh/vk/GrVkTypes.h>
#include <include/gpu/vk/VulkanBackendContext.h>
#include <ui/FatVector.h>
-#include <vk/GrVkTypes.h>
#include <sstream>
@@ -318,6 +318,15 @@
tailPNext = &deviceFaultFeatures->pNext;
}
+ if (grExtensions.hasExtension(VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME, 1)) {
+ VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT* formatFeatures =
+ new VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT;
+ formatFeatures->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT;
+ formatFeatures->pNext = nullptr;
+ *tailPNext = formatFeatures;
+ tailPNext = &formatFeatures->pNext;
+ }
+
// query to get the physical device features
mGetPhysicalDeviceFeatures2(mPhysicalDevice, &features);
// this looks like it would slow things down,
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 08f9d42..f042571 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -20,9 +20,9 @@
#if !defined(VK_USE_PLATFORM_ANDROID_KHR)
#define VK_USE_PLATFORM_ANDROID_KHR
#endif
-#include <GrContextOptions.h>
#include <SkSurface.h>
#include <android-base/unique_fd.h>
+#include <include/gpu/ganesh/GrContextOptions.h>
#include <utils/StrongPointer.h>
#include <vk/VulkanExtensions.h>
#include <vulkan/vulkan.h>
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index 0f29613..20c2b1a 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -16,12 +16,13 @@
#include "VulkanSurface.h"
-#include <include/android/SkSurfaceAndroid.h>
-#include <GrDirectContext.h>
#include <SkSurface.h>
+#include <gui/TraceUtils.h>
+#include <include/android/SkSurfaceAndroid.h>
+#include <include/gpu/ganesh/GrDirectContext.h>
+
#include <algorithm>
-#include <gui/TraceUtils.h>
#include "VulkanManager.h"
#include "utils/Color.h"
diff --git a/libs/hwui/tests/unit/ShaderCacheTests.cpp b/libs/hwui/tests/unit/ShaderCacheTests.cpp
index 0f8bd13..b714534 100644
--- a/libs/hwui/tests/unit/ShaderCacheTests.cpp
+++ b/libs/hwui/tests/unit/ShaderCacheTests.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <GrDirectContext.h>
#include <Properties.h>
#include <SkData.h>
#include <SkRefCnt.h>
@@ -22,6 +21,7 @@
#include <dirent.h>
#include <errno.h>
#include <gtest/gtest.h>
+#include <include/gpu/ganesh/GrDirectContext.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
diff --git a/libs/hwui/tests/unit/UnderlineTest.cpp b/libs/hwui/tests/unit/UnderlineTest.cpp
index c70a304..ecb06d8 100644
--- a/libs/hwui/tests/unit/UnderlineTest.cpp
+++ b/libs/hwui/tests/unit/UnderlineTest.cpp
@@ -109,9 +109,7 @@
return f;
}
-TEST_WITH_FLAGS(UnderlineTest, Roboto,
- REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::text::flags,
- fix_double_underline))) {
+TEST(UnderlineTest, Roboto) {
float textSize = 100;
Paint paint;
paint.getSkFont().setSize(textSize);
@@ -123,9 +121,7 @@
EXPECT_EQ(ROBOTO_THICKNESS_EM * textSize, functor.getUnderlineThickness());
}
-TEST_WITH_FLAGS(UnderlineTest, NotoCJK,
- REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::text::flags,
- fix_double_underline))) {
+TEST(UnderlineTest, NotoCJK) {
float textSize = 100;
Paint paint;
paint.getSkFont().setSize(textSize);
@@ -137,9 +133,7 @@
EXPECT_EQ(NOTO_CJK_THICKNESS_EM * textSize, functor.getUnderlineThickness());
}
-TEST_WITH_FLAGS(UnderlineTest, Mixture,
- REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::text::flags,
- fix_double_underline))) {
+TEST(UnderlineTest, Mixture) {
float textSize = 100;
Paint paint;
paint.getSkFont().setSize(textSize);
diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp
index 6a560b3..9673c5f 100644
--- a/libs/hwui/utils/Color.cpp
+++ b/libs/hwui/utils/Color.cpp
@@ -49,6 +49,10 @@
colorType = kRGBA_1010102_SkColorType;
alphaType = kPremul_SkAlphaType;
break;
+ case AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM:
+ colorType = kRGBA_10x6_SkColorType;
+ alphaType = kPremul_SkAlphaType;
+ break;
case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
colorType = kRGBA_F16_SkColorType;
alphaType = kPremul_SkAlphaType;
@@ -86,6 +90,8 @@
return AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM;
case kRGBA_1010102_SkColorType:
return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
+ case kRGBA_10x6_SkColorType:
+ return AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM;
case kARGB_4444_SkColorType:
// Hardcoding the value from android::PixelFormat
static constexpr uint64_t kRGBA4444 = 7;
@@ -108,6 +114,8 @@
return kRGB_565_SkColorType;
case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
return kRGBA_1010102_SkColorType;
+ case AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM:
+ return kRGBA_10x6_SkColorType;
case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
return kRGBA_F16_SkColorType;
case AHARDWAREBUFFER_FORMAT_R8_UNORM:
diff --git a/location/api/system-current.txt b/location/api/system-current.txt
index f6e76a2..cf3f740 100644
--- a/location/api/system-current.txt
+++ b/location/api/system-current.txt
@@ -437,7 +437,7 @@
}
public class LocationManager {
- method @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void addProviderRequestChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.provider.ProviderRequest.ChangedListener);
+ method @Deprecated @FlaggedApi("android.location.flags.deprecate_provider_request_apis") @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void addProviderRequestChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.provider.ProviderRequest.ChangedListener);
method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void flushGnssBatch();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
method @Nullable public String getExtraLocationControllerPackage();
@@ -452,7 +452,7 @@
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String, @Nullable String);
method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.UPDATE_APP_OPS_STATS}) public boolean registerGnssBatchedLocationCallback(long, boolean, @NonNull android.location.BatchedLocationCallback, @Nullable android.os.Handler);
method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void removeProviderRequestChangedListener(@NonNull android.location.provider.ProviderRequest.ChangedListener);
+ method @Deprecated @FlaggedApi("android.location.flags.deprecate_provider_request_apis") @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void removeProviderRequestChangedListener(@NonNull android.location.provider.ProviderRequest.ChangedListener);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index d921730..6342489 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -28,6 +28,7 @@
import android.Manifest;
import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresFeature;
@@ -47,6 +48,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.location.flags.Flags;
import android.location.provider.IProviderRequestListener;
import android.location.provider.ProviderProperties;
import android.location.provider.ProviderRequest;
@@ -2957,8 +2959,13 @@
*
* @param executor the executor that the callback runs on
* @param listener the listener to register
+ *
+ * @deprecated Do not use - this API was intended for testing only, and may not return any
+ * results in the future.
* @hide
*/
+ @FlaggedApi(Flags.FLAG_DEPRECATE_PROVIDER_REQUEST_APIS)
+ @Deprecated
@SystemApi
@RequiresPermission(allOf = {Manifest.permission.LOCATION_HARDWARE,
Manifest.permission.INTERACT_ACROSS_USERS})
@@ -2973,8 +2980,13 @@
* Removes a {@link ProviderRequest.ChangedListener} that has been added.
*
* @param listener the listener to remove.
+ *
+ * @deprecated Do not use - this API was intended for testing only, and may not return any
+ * results in the future.
* @hide
*/
+ @FlaggedApi(Flags.FLAG_DEPRECATE_PROVIDER_REQUEST_APIS)
+ @Deprecated
@SystemApi
@RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
public void removeProviderRequestChangedListener(
diff --git a/location/java/android/location/flags/location.aconfig b/location/java/android/location/flags/location.aconfig
index 0edaaef..3c387d3 100644
--- a/location/java/android/location/flags/location.aconfig
+++ b/location/java/android/location/flags/location.aconfig
@@ -2,6 +2,13 @@
container: "system"
flag {
+ name: "deprecate_provider_request_apis"
+ namespace: "location"
+ description: "Deprecates LocationManager ProviderChanged APIs"
+ bug: "361811782"
+}
+
+flag {
name: "keep_gnss_stationary_throttling"
namespace: "location"
description: "Keeps stationary throttling for the GNSS provider even if the disable_stationary_throttling flag is true."
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 25fae76..4981cb3 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -6984,6 +6984,27 @@
}
/**
+ * Test method for enabling/disabling the volume controller long press timeout for checking
+ * whether two consecutive volume adjustments should be treated as a volume long press.
+ *
+ * <p>Used only for testing
+ *
+ * @param enable true for enabling, otherwise will be disabled (test mode)
+ *
+ * @hide
+ **/
+ @TestApi
+ @SuppressLint("UnflaggedApi") // @TestApi without associated feature.
+ @RequiresPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED)
+ public void setVolumeControllerLongPressTimeoutEnabled(boolean enable) {
+ try {
+ getService().setVolumeControllerLongPressTimeoutEnabled(enable);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Only useful for volume controllers.
* @hide
*/
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index a96562d..9af6b28 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -303,6 +303,9 @@
void notifyVolumeControllerVisible(in IVolumeController controller, boolean visible);
+ @EnforcePermission("MODIFY_AUDIO_SETTINGS_PRIVILEGED")
+ oneway void setVolumeControllerLongPressTimeoutEnabled(boolean enable);
+
boolean isStreamAffectedByRingerMode(int streamType);
boolean isStreamAffectedByMute(int streamType);
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 1930c3d..b84990b 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -288,8 +288,7 @@
/**
* Returns a proxy MediaRouter2 instance that allows you to control the routing of an app
- * specified by {@code clientPackageName}. Returns {@code null} if the specified package name
- * does not exist.
+ * specified by {@code clientPackageName}.
*
* <p>Proxy MediaRouter2 instances operate differently than regular MediaRouter2 instances:
*
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index e78dc31..b448ecd 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -16,6 +16,8 @@
package android.media;
+import static android.media.Utils.parseVibrationEffect;
+
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentProvider;
@@ -24,17 +26,23 @@
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources.NotFoundException;
import android.database.Cursor;
+import android.media.audio.Flags;
import android.media.audiofx.HapticGenerator;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.RemoteException;
import android.os.Trace;
+import android.os.VibrationAttributes;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
import android.provider.MediaStore;
import android.provider.MediaStore.MediaColumns;
import android.provider.Settings;
import android.util.Log;
+
import com.android.internal.annotations.VisibleForTesting;
+
import java.io.IOException;
import java.util.ArrayList;
@@ -62,6 +70,11 @@
// keep references on active Ringtones until stopped or completion listener called.
private static final ArrayList<Ringtone> sActiveRingtones = new ArrayList<Ringtone>();
+ private static final VibrationAttributes VIBRATION_ATTRIBUTES =
+ new VibrationAttributes.Builder().setUsage(VibrationAttributes.USAGE_RINGTONE).build();
+
+ private static final int VIBRATION_LOOP_DELAY_MS = 200;
+
private final Context mContext;
private final AudioManager mAudioManager;
private VolumeShaper.Configuration mVolumeShaperConfig;
@@ -95,6 +108,10 @@
private float mVolume = 1.0f;
private boolean mHapticGeneratorEnabled = false;
private final Object mPlaybackSettingsLock = new Object();
+ private final Vibrator mVibrator;
+ private final boolean mRingtoneVibrationSupported;
+ private VibrationEffect mVibrationEffect;
+ private boolean mIsVibrating;
/** {@hide} */
@UnsupportedAppUsage
@@ -104,6 +121,8 @@
mAllowRemote = allowRemote;
mRemotePlayer = allowRemote ? mAudioManager.getRingtonePlayer() : null;
mRemoteToken = allowRemote ? new Binder() : null;
+ mVibrator = mContext.getSystemService(Vibrator.class);
+ mRingtoneVibrationSupported = Utils.isRingtoneVibrationSettingsSupported(mContext);
}
/**
@@ -487,6 +506,23 @@
if (mUri == null) {
destroyLocalPlayer();
}
+ if (Flags.enableRingtoneHapticsCustomization()
+ && mRingtoneVibrationSupported && mUri != null) {
+ mVibrationEffect = parseVibrationEffect(mVibrator, Utils.getVibrationUri(mUri));
+ if (mVibrationEffect != null) {
+ mVibrationEffect =
+ mVibrationEffect.applyRepeatingIndefinitely(true, VIBRATION_LOOP_DELAY_MS);
+ }
+ }
+ }
+
+ /**
+ * Returns the {@link VibrationEffect} has been created for this ringtone.
+ * @hide
+ */
+ @VisibleForTesting
+ public VibrationEffect getVibrationEffect() {
+ return mVibrationEffect;
}
/** {@hide} */
@@ -530,6 +566,17 @@
Log.w(TAG, "Neither local nor remote playback available");
}
}
+ if (Flags.enableRingtoneHapticsCustomization() && mRingtoneVibrationSupported) {
+ playVibration();
+ }
+ }
+
+ private void playVibration() {
+ if (mVibrationEffect == null) {
+ return;
+ }
+ mIsVibrating = true;
+ mVibrator.vibrate(mVibrationEffect, VIBRATION_ATTRIBUTES);
}
/**
@@ -545,6 +592,11 @@
Log.w(TAG, "Problem stopping ringtone: " + e);
}
}
+ if (Flags.enableRingtoneHapticsCustomization()
+ && mRingtoneVibrationSupported && mIsVibrating) {
+ mVibrator.cancel();
+ mIsVibrating = false;
+ }
}
private void destroyLocalPlayer() {
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 47e3a0f..f0ab6ec 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -34,6 +34,7 @@
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.database.StaleDataException;
+import android.media.audio.Flags;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
@@ -809,6 +810,12 @@
// Don't set the stream type
Ringtone ringtone = getRingtone(context, ringtoneUri, -1 /* streamType */,
volumeShaperConfig, false);
+ if (Flags.enableRingtoneHapticsCustomization()
+ && Utils.isRingtoneVibrationSettingsSupported(context)
+ && Utils.hasVibration(ringtoneUri) && hasHapticChannels(ringtoneUri)) {
+ audioAttributes = new AudioAttributes.Builder(
+ audioAttributes).setHapticChannelsMuted(true).build();
+ }
if (ringtone != null) {
ringtone.setAudioAttributesField(audioAttributes);
if (!ringtone.createLocalMediaPlayer()) {
diff --git a/media/java/android/media/Utils.java b/media/java/android/media/Utils.java
index d07f611..41e9b65 100644
--- a/media/java/android/media/Utils.java
+++ b/media/java/android/media/Utils.java
@@ -20,12 +20,17 @@
import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.os.Binder;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
+import android.os.vibrator.persistence.ParsedVibration;
+import android.os.vibrator.persistence.VibrationXmlParser;
import android.provider.OpenableColumns;
import android.util.Log;
import android.util.Pair;
@@ -36,7 +41,11 @@
import com.android.internal.annotations.GuardedBy;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
@@ -55,6 +64,8 @@
public class Utils {
private static final String TAG = "Utils";
+ public static final String VIBRATION_URI_PARAM = "vibration_uri";
+
/**
* Sorts distinct (non-intersecting) range array in ascending order.
* @throws java.lang.IllegalArgumentException if ranges are not distinct
@@ -688,4 +699,78 @@
}
return anonymizeBluetoothAddress(address);
}
+
+ /**
+ * Whether the device supports ringtone vibration settings.
+ *
+ * @param context the {@link Context}
+ * @return {@code true} if the device supports ringtone vibration
+ */
+ public static boolean isRingtoneVibrationSettingsSupported(Context context) {
+ final Resources res = context.getResources();
+ return res != null && res.getBoolean(
+ com.android.internal.R.bool.config_ringtoneVibrationSettingsSupported);
+ }
+
+ /**
+ * Whether the given ringtone Uri has vibration Uri parameter
+ *
+ * @param ringtoneUri the ringtone Uri
+ * @return {@code true} if the Uri has vibration parameter
+ */
+ public static boolean hasVibration(Uri ringtoneUri) {
+ final String vibrationUriString = ringtoneUri.getQueryParameter(VIBRATION_URI_PARAM);
+ return vibrationUriString != null;
+ }
+
+ /**
+ * Gets the vibration Uri from given ringtone Uri
+ *
+ * @param ringtoneUri the ringtone Uri
+ * @return parsed {@link Uri} of vibration parameter, {@code null} if the vibration parameter
+ * is not found.
+ */
+ public static Uri getVibrationUri(Uri ringtoneUri) {
+ final String vibrationUriString = ringtoneUri.getQueryParameter(VIBRATION_URI_PARAM);
+ if (vibrationUriString == null) {
+ return null;
+ }
+ return Uri.parse(vibrationUriString);
+ }
+
+ /**
+ * Returns the parsed {@link VibrationEffect} from given vibration Uri.
+ *
+ * @param vibrator the vibrator to resolve the vibration file
+ * @param vibrationUri the vibration file Uri to represent a vibration
+ */
+ @SuppressWarnings("FlaggedApi") // VibrationXmlParser is available internally as hidden APIs.
+ public static VibrationEffect parseVibrationEffect(Vibrator vibrator, Uri vibrationUri) {
+ if (vibrationUri == null) {
+ Log.w(TAG, "The vibration Uri is null.");
+ return null;
+ }
+ String filePath = vibrationUri.getPath();
+ if (filePath == null) {
+ Log.w(TAG, "The file path is null.");
+ return null;
+ }
+ File vibrationFile = new File(filePath);
+ if (vibrationFile.exists() && vibrationFile.canRead()) {
+ try {
+ FileInputStream fileInputStream = new FileInputStream(vibrationFile);
+ ParsedVibration parsedVibration =
+ VibrationXmlParser.parseDocument(
+ new InputStreamReader(fileInputStream, StandardCharsets.UTF_8));
+ return parsedVibration.resolve(vibrator);
+ } catch (IOException e) {
+ Log.e(TAG, "FileNotFoundException" + e);
+ }
+ } else {
+ // File not found or cannot be read
+ Log.w(TAG, "File exists:" + vibrationFile.exists()
+ + ", canRead:" + vibrationFile.canRead());
+ }
+ return null;
+ }
}
diff --git a/media/native/midi/Android.bp b/media/native/midi/Android.bp
index a991a71f..7acb8c7 100644
--- a/media/native/midi/Android.bp
+++ b/media/native/midi/Android.bp
@@ -74,8 +74,4 @@
symbol_file: "libamidi.map.txt",
first_version: "29",
- export_header_libs: [
- "amidi",
- ],
-
}
diff --git a/media/tests/AudioPolicyTest/Android.bp b/media/tests/AudioPolicyTest/Android.bp
index 3dc2a0a..43b1a35 100644
--- a/media/tests/AudioPolicyTest/Android.bp
+++ b/media/tests/AudioPolicyTest/Android.bp
@@ -24,3 +24,11 @@
resource_dirs: ["res"],
test_suites: ["device-tests"],
}
+
+test_module_config {
+ name: "audiopolicytest_audiopolicytest_audiopolicydeathtest_Presubmit",
+ base: "audiopolicytest",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.audiopolicytest.AudioPolicyDeathTest"],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
diff --git a/native/android/Android.bp b/native/android/Android.bp
index c4c4102..3eb99c3 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -27,9 +27,6 @@
symbol_file: "libandroid.map.txt",
first_version: "9",
unversioned_until: "current",
- export_header_libs: [
- "libandroid_headers",
- ],
}
cc_defaults {
diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt
index 0f97b2c..cc5ff81 100644
--- a/nfc/api/system-current.txt
+++ b/nfc/api/system-current.txt
@@ -82,6 +82,7 @@
method public void onEnableStarted();
method public void onHceEventReceived(int);
method public void onNdefRead(@NonNull java.util.function.Consumer<java.lang.Boolean>);
+ method public void onReaderOptionChanged(boolean);
method public void onRfDiscoveryStarted(boolean);
method public void onRfFieldActivated(boolean);
method public void onRoutingChanged();
@@ -97,6 +98,7 @@
public final class CardEmulation {
method @FlaggedApi("android.permission.flags.wallet_role_enabled") @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static android.content.ComponentName getPreferredPaymentService(@NonNull android.content.Context);
method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public java.util.List<android.nfc.cardemulation.ApduServiceInfo> getServices(@NonNull String, int);
+ method @FlaggedApi("android.nfc.enable_card_emulation_euicc") public boolean isEuiccSupported();
method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public void overrideRoutingTable(@NonNull android.app.Activity, int, int);
method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public void recoverRoutingTable(@NonNull android.app.Activity);
}
diff --git a/nfc/java/android/nfc/INfcCardEmulation.aidl b/nfc/java/android/nfc/INfcCardEmulation.aidl
index 79f1275..19b9e0f 100644
--- a/nfc/java/android/nfc/INfcCardEmulation.aidl
+++ b/nfc/java/android/nfc/INfcCardEmulation.aidl
@@ -50,4 +50,5 @@
void overrideRoutingTable(int userHandle, String protocol, String technology, in String pkg);
void recoverRoutingTable(int userHandle);
+ boolean isEuiccSupported();
}
diff --git a/nfc/java/android/nfc/INfcOemExtensionCallback.aidl b/nfc/java/android/nfc/INfcOemExtensionCallback.aidl
index b65c837..e49ef7e 100644
--- a/nfc/java/android/nfc/INfcOemExtensionCallback.aidl
+++ b/nfc/java/android/nfc/INfcOemExtensionCallback.aidl
@@ -37,6 +37,7 @@
void onTagDispatch(in ResultReceiver isSkipped);
void onRoutingChanged();
void onHceEventReceived(int action);
+ void onReaderOptionChanged(boolean enabled);
void onCardEmulationActivated(boolean isActivated);
void onRfFieldActivated(boolean isActivated);
void onRfDiscoveryStarted(boolean isDiscoveryStarted);
diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java
index 22ae612..f478793 100644
--- a/nfc/java/android/nfc/NfcAdapter.java
+++ b/nfc/java/android/nfc/NfcAdapter.java
@@ -721,7 +721,7 @@
*
* @return List<String> containing secure elements on the device which supports
* off host card emulation. eSE for Embedded secure element,
- * SIM for UICC and so on.
+ * SIM for UICC, eSIM for EUICC and so on.
* @hide
*/
public @NonNull List<String> getSupportedOffHostSecureElements() {
@@ -741,6 +741,11 @@
if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE)) {
offHostSE.add("eSE");
}
+ if (Flags.enableCardEmulationEuicc()
+ && callServiceReturn(
+ () -> sCardEmulationService.isEuiccSupported(), false)) {
+ offHostSE.add("eSIM");
+ }
return offHostSE;
}
diff --git a/nfc/java/android/nfc/NfcOemExtension.java b/nfc/java/android/nfc/NfcOemExtension.java
index 632f693..d51b704 100644
--- a/nfc/java/android/nfc/NfcOemExtension.java
+++ b/nfc/java/android/nfc/NfcOemExtension.java
@@ -223,6 +223,13 @@
void onHceEventReceived(@HostCardEmulationAction int action);
/**
+ * API to notify when reader option has been changed using
+ * {@link NfcAdapter#enableReaderOption(boolean)} by some app.
+ * @param enabled Flag indicating ReaderMode enabled/disabled
+ */
+ void onReaderOptionChanged(boolean enabled);
+
+ /**
* Notifies NFC is activated in listen mode.
* NFC Forum NCI-2.3 ch.5.2.6 specification
*
@@ -488,6 +495,12 @@
handleVoidCallback(action, cb::onHceEventReceived, ex));
}
+ @Override
+ public void onReaderOptionChanged(boolean enabled) throws RemoteException {
+ mCallbackMap.forEach((cb, ex) ->
+ handleVoidCallback(enabled, cb::onReaderOptionChanged, ex));
+ }
+
private <T> void handleVoidCallback(
T input, Consumer<T> callbackMethod, Executor executor) {
synchronized (mLock) {
diff --git a/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java
index 3cf0a4d..ea5a036 100644
--- a/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -308,6 +308,8 @@
mOffHostName = "eSE1";
} else if (mOffHostName.equals("SIM")) {
mOffHostName = "SIM1";
+ } else if (Flags.enableCardEmulationEuicc() && mOffHostName.equals("eSIM")) {
+ mOffHostName = "eSIM1";
}
}
mStaticOffHostName = mOffHostName;
diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java
index 497309c..a72a896 100644
--- a/nfc/java/android/nfc/cardemulation/CardEmulation.java
+++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java
@@ -548,11 +548,13 @@
List<String> validSE = adapter.getSupportedOffHostSecureElements();
if ((offHostSecureElement.startsWith("eSE") && !validSE.contains("eSE"))
- || (offHostSecureElement.startsWith("SIM") && !validSE.contains("SIM"))) {
+ || (offHostSecureElement.startsWith("SIM") && !validSE.contains("SIM"))
+ || (offHostSecureElement.startsWith("eSIM") && !validSE.contains("eSIM"))) {
return false;
}
- if (!offHostSecureElement.startsWith("eSE") && !offHostSecureElement.startsWith("SIM")) {
+ if (!offHostSecureElement.startsWith("eSE") && !offHostSecureElement.startsWith("SIM")
+ && !(Flags.enableCardEmulationEuicc() && offHostSecureElement.startsWith("eSIM"))) {
return false;
}
@@ -560,6 +562,8 @@
offHostSecureElement = "eSE1";
} else if (offHostSecureElement.equals("SIM")) {
offHostSecureElement = "SIM1";
+ } else if (Flags.enableCardEmulationEuicc() && offHostSecureElement.equals("eSIM")) {
+ offHostSecureElement = "eSIM1";
}
final String offHostSecureElementV = new String(offHostSecureElement);
return callServiceReturn(() ->
@@ -985,6 +989,18 @@
}
/**
+ * Is EUICC supported as a Secure Element EE which supports off host card emulation.
+ *
+ * @return true if the device supports EUICC for off host card emulation, false otherwise.
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC)
+ public boolean isEuiccSupported() {
+ return callServiceReturn(() -> sService.isEuiccSupported(), false);
+ }
+
+ /**
* Returns the value of {@link Settings.Secure#NFC_PAYMENT_DEFAULT_COMPONENT}.
*
* @param context A context
diff --git a/nfc/java/android/nfc/flags.aconfig b/nfc/java/android/nfc/flags.aconfig
index 0ade4db..cc9a97c 100644
--- a/nfc/java/android/nfc/flags.aconfig
+++ b/nfc/java/android/nfc/flags.aconfig
@@ -148,4 +148,12 @@
namespace: "nfc"
description: "Enable watchdog for the NFC system process"
bug: "362937338"
-}
\ No newline at end of file
+}
+
+flag {
+ name: "enable_card_emulation_euicc"
+ is_exported: true
+ namespace: "nfc"
+ description: "Enable EUICC card emulation"
+ bug: "321314635"
+}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index ff09084..c4173ed 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -460,7 +460,7 @@
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK) {
+ if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE) {
event.startTracking();
return true;
}
@@ -479,7 +479,7 @@
return true;
}
- if (keyCode == KeyEvent.KEYCODE_BACK
+ if ((keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE)
&& event.isTracking() && !event.isCanceled()) {
if (mPrintPreviewController != null && mPrintPreviewController.isOptionsOpened()
&& !hasErrors()) {
diff --git a/packages/SettingsLib/DataStore/Android.bp b/packages/SettingsLib/DataStore/Android.bp
index 86c8f0da..6840e10 100644
--- a/packages/SettingsLib/DataStore/Android.bp
+++ b/packages/SettingsLib/DataStore/Android.bp
@@ -17,6 +17,7 @@
"androidx.annotation_annotation",
"androidx.collection_collection-ktx",
"androidx.core_core-ktx",
+ "error_prone_annotations",
"guava",
],
kotlincflags: ["-Xjvm-default=all"],
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/KeyValueStore.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/KeyValueStore.kt
new file mode 100644
index 0000000..3d41337
--- /dev/null
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/KeyValueStore.kt
@@ -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 com.android.settingslib.datastore
+
+import android.content.SharedPreferences
+
+/** Interface of key-value store. */
+interface KeyValueStore : KeyedObservable<String> {
+
+ /** Returns if the storage contains persistent value of given key. */
+ fun contains(key: String): Boolean
+
+ /** Gets default value of given key. */
+ fun <T : Any> getDefaultValue(key: String, valueType: Class<T>): T? =
+ when (valueType) {
+ Boolean::class.javaObjectType -> false
+ Float::class.javaObjectType -> 0f
+ Int::class.javaObjectType -> 0
+ Long::class.javaObjectType -> 0
+ else -> null
+ }
+ as T?
+
+ /** Gets value of given key. */
+ fun <T : Any> getValue(key: String, valueType: Class<T>): T?
+
+ /**
+ * Sets value for given key.
+ *
+ * @param key key
+ * @param valueType value type
+ * @param value value to set, null means remove
+ */
+ fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?)
+}
+
+/** [SharedPreferences] based [KeyValueStore]. */
+interface SharedPreferencesKeyValueStore : KeyValueStore {
+
+ /** [SharedPreferences] of the key-value store. */
+ val sharedPreferences: SharedPreferences
+
+ override fun contains(key: String): Boolean = sharedPreferences.contains(key)
+
+ override fun <T : Any> getValue(key: String, valueType: Class<T>): T? =
+ when (valueType) {
+ Boolean::class.javaObjectType -> sharedPreferences.getBoolean(key, false)
+ Float::class.javaObjectType -> sharedPreferences.getFloat(key, 0f)
+ Int::class.javaObjectType -> sharedPreferences.getInt(key, 0)
+ Long::class.javaObjectType -> sharedPreferences.getLong(key, 0)
+ String::class.javaObjectType -> sharedPreferences.getString(key, null)
+ Set::class.javaObjectType -> sharedPreferences.getStringSet(key, null)
+ else -> null
+ }
+ as T?
+
+ override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
+ if (value == null) {
+ sharedPreferences.edit().remove(key).apply()
+ return
+ }
+ val edit = sharedPreferences.edit()
+ when (valueType) {
+ Boolean::class.javaObjectType -> edit.putBoolean(key, value as Boolean)
+ Float::class.javaObjectType -> edit.putFloat(key, value as Float)
+ Int::class.javaObjectType -> edit.putInt(key, value as Int)
+ Long::class.javaObjectType -> edit.putLong(key, value as Long)
+ String::class.javaObjectType -> edit.putString(key, value as String)
+ Set::class.javaObjectType -> edit.putStringSet(key, value as Set<String>)
+ else -> {}
+ }
+ edit.apply()
+ }
+}
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/KeyedObserver.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/KeyedObserver.kt
index 4ce1d37..ec90317 100644
--- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/KeyedObserver.kt
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/KeyedObserver.kt
@@ -19,6 +19,7 @@
import androidx.annotation.AnyThread
import androidx.annotation.GuardedBy
import androidx.collection.MutableScatterMap
+import com.google.errorprone.annotations.CanIgnoreReturnValue
import java.util.WeakHashMap
import java.util.concurrent.Executor
@@ -62,8 +63,9 @@
*
* @param observer observer to be notified
* @param executor executor to run the callback
+ * @return if the observer is newly added
*/
- fun addObserver(observer: KeyedObserver<K?>, executor: Executor)
+ @CanIgnoreReturnValue fun addObserver(observer: KeyedObserver<K?>, executor: Executor): Boolean
/**
* Adds an observer on given key.
@@ -73,14 +75,24 @@
* @param key key to observe
* @param observer observer to be notified
* @param executor executor to run the callback
+ * @return if the observer is newly added
*/
- fun addObserver(key: K, observer: KeyedObserver<K>, executor: Executor)
+ @CanIgnoreReturnValue
+ fun addObserver(key: K, observer: KeyedObserver<K>, executor: Executor): Boolean
- /** Removes observer. */
- fun removeObserver(observer: KeyedObserver<K?>)
+ /**
+ * Removes observer.
+ *
+ * @return if the observer is found and removed
+ */
+ @CanIgnoreReturnValue fun removeObserver(observer: KeyedObserver<K?>): Boolean
- /** Removes observer on given key. */
- fun removeObserver(key: K, observer: KeyedObserver<K>)
+ /**
+ * Removes observer on given key.
+ *
+ * @return if the observer is found and removed
+ */
+ @CanIgnoreReturnValue fun removeObserver(key: K, observer: KeyedObserver<K>): Boolean
/**
* Notifies all observers that a change occurs.
@@ -111,14 +123,17 @@
@GuardedBy("itself")
private val keyedObservers = MutableScatterMap<K, WeakHashMap<KeyedObserver<K>, Executor>>()
- override fun addObserver(observer: KeyedObserver<K?>, executor: Executor) {
+ @CanIgnoreReturnValue
+ override fun addObserver(observer: KeyedObserver<K?>, executor: Executor): Boolean {
val oldExecutor = synchronized(observers) { observers.put(observer, executor) }
if (oldExecutor != null && oldExecutor != executor) {
throw IllegalStateException("Add $observer twice, old=$oldExecutor, new=$executor")
}
+ return oldExecutor == null
}
- override fun addObserver(key: K, observer: KeyedObserver<K>, executor: Executor) {
+ @CanIgnoreReturnValue
+ override fun addObserver(key: K, observer: KeyedObserver<K>, executor: Executor): Boolean {
val oldExecutor =
synchronized(keyedObservers) {
keyedObservers.getOrPut(key) { WeakHashMap() }.put(observer, executor)
@@ -126,20 +141,23 @@
if (oldExecutor != null && oldExecutor != executor) {
throw IllegalStateException("Add $observer twice, old=$oldExecutor, new=$executor")
}
+ return oldExecutor == null
}
- override fun removeObserver(observer: KeyedObserver<K?>) {
- synchronized(observers) { observers.remove(observer) }
- }
+ @CanIgnoreReturnValue
+ override fun removeObserver(observer: KeyedObserver<K?>) =
+ synchronized(observers) { observers.remove(observer) } != null
- override fun removeObserver(key: K, observer: KeyedObserver<K>) {
+ @CanIgnoreReturnValue
+ override fun removeObserver(key: K, observer: KeyedObserver<K>) =
synchronized(keyedObservers) {
- val observers = keyedObservers[key]
- if (observers?.remove(observer) != null && observers.isEmpty()) {
+ val observers = keyedObservers[key] ?: return false
+ val removed = observers.remove(observer) != null
+ if (removed && observers.isEmpty()) {
keyedObservers.remove(key)
}
+ removed
}
- }
override fun notifyChange(reason: Int) {
// make a copy to avoid potential ConcurrentModificationException
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsGlobalStore.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsGlobalStore.kt
new file mode 100644
index 0000000..4aef0fc
--- /dev/null
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsGlobalStore.kt
@@ -0,0 +1,81 @@
+/*
+ * 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.settingslib.datastore
+
+import android.content.ContentResolver
+import android.content.Context
+import android.provider.Settings.Global
+import android.provider.Settings.SettingNotFoundException
+
+/**
+ * [KeyValueStore] for [Global] settings.
+ *
+ * By default, a boolean type `true` value is stored as `1` and `false` value is stored as `0`.
+ */
+class SettingsGlobalStore private constructor(contentResolver: ContentResolver) :
+ SettingsStore(contentResolver) {
+
+ override val tag: String
+ get() = "SettingsGlobalStore"
+
+ override fun contains(key: String): Boolean = Global.getString(contentResolver, key) != null
+
+ override fun <T : Any> getValue(key: String, valueType: Class<T>): T? =
+ try {
+ when (valueType) {
+ Boolean::class.javaObjectType -> Global.getInt(contentResolver, key) != 0
+ Float::class.javaObjectType -> Global.getFloat(contentResolver, key)
+ Int::class.javaObjectType -> Global.getInt(contentResolver, key)
+ Long::class.javaObjectType -> Global.getLong(contentResolver, key)
+ String::class.javaObjectType -> Global.getString(contentResolver, key)
+ else -> throw UnsupportedOperationException("Get $key $valueType")
+ }
+ as T?
+ } catch (e: SettingNotFoundException) {
+ null
+ }
+
+ override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
+ if (value == null) {
+ Global.putString(contentResolver, key, null)
+ return
+ }
+ when (valueType) {
+ Boolean::class.javaObjectType ->
+ Global.putInt(contentResolver, key, if (value == true) 1 else 0)
+ Float::class.javaObjectType -> Global.putFloat(contentResolver, key, value as Float)
+ Int::class.javaObjectType -> Global.putInt(contentResolver, key, value as Int)
+ Long::class.javaObjectType -> Global.putLong(contentResolver, key, value as Long)
+ String::class.javaObjectType -> Global.putString(contentResolver, key, value as String)
+ else -> throw UnsupportedOperationException("Set $key $valueType")
+ }
+ }
+
+ companion object {
+ @Volatile private var instance: SettingsGlobalStore? = null
+
+ @JvmStatic
+ fun get(context: Context): SettingsGlobalStore =
+ instance
+ ?: synchronized(this) {
+ instance
+ ?: SettingsGlobalStore(context.applicationContext.contentResolver).also {
+ instance = it
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSecureStore.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSecureStore.kt
new file mode 100644
index 0000000..9f41ecb
--- /dev/null
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSecureStore.kt
@@ -0,0 +1,81 @@
+/*
+ * 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.settingslib.datastore
+
+import android.content.ContentResolver
+import android.content.Context
+import android.provider.Settings.Secure
+import android.provider.Settings.SettingNotFoundException
+
+/**
+ * [KeyValueStore] for [Secure] settings.
+ *
+ * By default, a boolean type `true` value is stored as `1` and `false` value is stored as `0`.
+ */
+class SettingsSecureStore private constructor(contentResolver: ContentResolver) :
+ SettingsStore(contentResolver) {
+
+ override val tag: String
+ get() = "SettingsSecureStore"
+
+ override fun contains(key: String): Boolean = Secure.getString(contentResolver, key) != null
+
+ override fun <T : Any> getValue(key: String, valueType: Class<T>): T? =
+ try {
+ when (valueType) {
+ Boolean::class.javaObjectType -> Secure.getInt(contentResolver, key) != 0
+ Float::class.javaObjectType -> Secure.getFloat(contentResolver, key)
+ Int::class.javaObjectType -> Secure.getInt(contentResolver, key)
+ Long::class.javaObjectType -> Secure.getLong(contentResolver, key)
+ String::class.javaObjectType -> Secure.getString(contentResolver, key)
+ else -> throw UnsupportedOperationException("Get $key $valueType")
+ }
+ as T?
+ } catch (e: SettingNotFoundException) {
+ null
+ }
+
+ override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
+ if (value == null) {
+ Secure.putString(contentResolver, key, null)
+ return
+ }
+ when (valueType) {
+ Boolean::class.javaObjectType ->
+ Secure.putInt(contentResolver, key, if (value == true) 1 else 0)
+ Float::class.javaObjectType -> Secure.putFloat(contentResolver, key, value as Float)
+ Int::class.javaObjectType -> Secure.putInt(contentResolver, key, value as Int)
+ Long::class.javaObjectType -> Secure.putLong(contentResolver, key, value as Long)
+ String::class.javaObjectType -> Secure.putString(contentResolver, key, value as String)
+ else -> throw UnsupportedOperationException("Set $key $valueType")
+ }
+ }
+
+ companion object {
+ @Volatile private var instance: SettingsSecureStore? = null
+
+ @JvmStatic
+ fun get(context: Context): SettingsSecureStore =
+ instance
+ ?: synchronized(this) {
+ instance
+ ?: SettingsSecureStore(context.applicationContext.contentResolver).also {
+ instance = it
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsStore.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsStore.kt
new file mode 100644
index 0000000..5981688
--- /dev/null
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsStore.kt
@@ -0,0 +1,104 @@
+/*
+ * 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.settingslib.datastore
+
+import android.content.ContentResolver
+import android.database.ContentObserver
+import android.net.Uri
+import android.os.Handler
+import android.os.Looper
+import android.provider.Settings
+import android.util.Log
+import java.util.concurrent.Executor
+import java.util.concurrent.atomic.AtomicInteger
+
+/** Base class of the Settings provider data stores. */
+open abstract class SettingsStore(protected val contentResolver: ContentResolver) :
+ KeyedDataObservable<String>(), KeyValueStore {
+
+ /**
+ * Counter of observers.
+ *
+ * The value is accurate only when [addObserver] and [removeObserver] are called correctly. When
+ * an observer is not removed (and its weak reference is garbage collected), the content
+ * observer is not unregistered but this is not a big deal.
+ */
+ private val counter = AtomicInteger()
+
+ private val contentObserver =
+ object : ContentObserver(Handler(Looper.getMainLooper())) {
+ override fun onChange(selfChange: Boolean) {
+ super.onChange(selfChange, null)
+ }
+
+ override fun onChange(selfChange: Boolean, uri: Uri?) {
+ val key = uri?.lastPathSegment ?: return
+ notifyChange(key, DataChangeReason.UPDATE)
+ }
+ }
+
+ override fun addObserver(observer: KeyedObserver<String?>, executor: Executor) =
+ if (super.addObserver(observer, executor)) {
+ onObserverAdded()
+ true
+ } else {
+ false
+ }
+
+ override fun addObserver(key: String, observer: KeyedObserver<String>, executor: Executor) =
+ if (super.addObserver(key, observer, executor)) {
+ onObserverAdded()
+ true
+ } else {
+ false
+ }
+
+ private fun onObserverAdded() {
+ if (counter.getAndIncrement() != 0) return
+ Log.i(tag, "registerContentObserver")
+ contentResolver.registerContentObserver(
+ Settings.Global.getUriFor(""),
+ true,
+ contentObserver,
+ )
+ }
+
+ override fun removeObserver(observer: KeyedObserver<String?>) =
+ if (super.removeObserver(observer)) {
+ onObserverRemoved()
+ true
+ } else {
+ false
+ }
+
+ override fun removeObserver(key: String, observer: KeyedObserver<String>) =
+ if (super.removeObserver(key, observer)) {
+ onObserverRemoved()
+ true
+ } else {
+ false
+ }
+
+ private fun onObserverRemoved() {
+ if (counter.decrementAndGet() != 0) return
+ Log.i(tag, "unregisterContentObserver")
+ contentResolver.unregisterContentObserver(contentObserver)
+ }
+
+ /** Tag for logging. */
+ abstract val tag: String
+}
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSystemStore.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSystemStore.kt
new file mode 100644
index 0000000..6cca7ed
--- /dev/null
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSystemStore.kt
@@ -0,0 +1,81 @@
+/*
+ * 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.settingslib.datastore
+
+import android.content.ContentResolver
+import android.content.Context
+import android.provider.Settings.SettingNotFoundException
+import android.provider.Settings.System
+
+/**
+ * [KeyValueStore] for [System] settings.
+ *
+ * By default, a boolean type `true` value is stored as `1` and `false` value is stored as `0`.
+ */
+class SettingsSystemStore private constructor(contentResolver: ContentResolver) :
+ SettingsStore(contentResolver) {
+
+ override val tag: String
+ get() = "SettingsSystemStore"
+
+ override fun contains(key: String): Boolean = System.getString(contentResolver, key) != null
+
+ override fun <T : Any> getValue(key: String, valueType: Class<T>): T? =
+ try {
+ when (valueType) {
+ Boolean::class.javaObjectType -> System.getInt(contentResolver, key) != 0
+ Float::class.javaObjectType -> System.getFloat(contentResolver, key)
+ Int::class.javaObjectType -> System.getInt(contentResolver, key)
+ Long::class.javaObjectType -> System.getLong(contentResolver, key)
+ String::class.javaObjectType -> System.getString(contentResolver, key)
+ else -> throw UnsupportedOperationException("Get $key $valueType")
+ }
+ as T?
+ } catch (e: SettingNotFoundException) {
+ null
+ }
+
+ override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
+ if (value == null) {
+ System.putString(contentResolver, key, null)
+ return
+ }
+ when (valueType) {
+ Boolean::class.javaObjectType ->
+ System.putInt(contentResolver, key, if (value == true) 1 else 0)
+ Float::class.javaObjectType -> System.putFloat(contentResolver, key, value as Float)
+ Int::class.javaObjectType -> System.putInt(contentResolver, key, value as Int)
+ Long::class.javaObjectType -> System.putLong(contentResolver, key, value as Long)
+ String::class.javaObjectType -> System.putString(contentResolver, key, value as String)
+ else -> throw UnsupportedOperationException("Set $key $valueType")
+ }
+ }
+
+ companion object {
+ @Volatile private var instance: SettingsSystemStore? = null
+
+ @JvmStatic
+ fun get(context: Context): SettingsSystemStore =
+ instance
+ ?: synchronized(this) {
+ instance
+ ?: SettingsSystemStore(context.applicationContext.contentResolver).also {
+ instance = it
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt
index 0ca91cd..ea17a56 100644
--- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SharedPreferencesStorage.kt
@@ -40,8 +40,9 @@
* Note that existing entries in the SharedPreferences will NOT be deleted before restore.
*
* @param context Context to get SharedPreferences
- * @param name Name of the SharedPreferences
- * @param mode Operating mode, see [Context.getSharedPreferences]
+ * @param name Name of the backup restore storage
+ * @param sharedPreferences SharedPreferences object
+ * @param filePath shared preferences file path relative to data dir
* @param verbose Verbose logging on key/value pairs during backup/restore. Enable for dev only!
* @param filter Filter of key/value pairs for backup and restore.
*/
@@ -50,12 +51,14 @@
constructor(
context: Context,
override val name: String,
- @get:VisibleForTesting internal val sharedPreferences: SharedPreferences,
+ override val sharedPreferences: SharedPreferences,
+ filePath: String = getSharedPreferencesFilePath(context, name),
private val codec: BackupCodec? = null,
private val verbose: Boolean = defaultVerbose(),
private val filter: (String, Any?) -> Boolean = { _, _ -> true },
) :
- BackupRestoreFileStorage(context, context.getSharedPreferencesFilePath(name)),
+ BackupRestoreFileStorage(context, filePath),
+ SharedPreferencesKeyValueStore,
KeyedObservable<String> by KeyedDataObservable() {
@JvmOverloads
@@ -66,7 +69,15 @@
codec: BackupCodec? = null,
verbose: Boolean = defaultVerbose(),
filter: (String, Any?) -> Boolean = { _, _ -> true },
- ) : this(context, name, context.getSharedPreferences(name, mode), codec, verbose, filter)
+ ) : this(
+ context,
+ name,
+ context.getSharedPreferences(name, mode),
+ getSharedPreferencesFilePath(context, name),
+ codec,
+ verbose,
+ filter,
+ )
/** Name of the intermediate SharedPreferences. */
@VisibleForTesting
@@ -80,7 +91,15 @@
return context.getSharedPreferences(intermediateName, Context.MODE_MULTI_PROCESS)
}
- private val sharedPreferencesListener = createSharedPreferenceListener()
+ private val sharedPreferencesListener =
+ SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
+ if (key != null) {
+ notifyChange(key, DataChangeReason.UPDATE)
+ } else {
+ // On Android >= R, SharedPreferences.Editor.clear() will trigger this case
+ notifyChange(DataChangeReason.DELETE)
+ }
+ }
init {
// listener is weakly referenced, so unregister is optional
@@ -183,7 +202,8 @@
else -> {
Log.e(
LOG_TAG,
- "[$name] $operation $key=$value, unknown type: ${value?.javaClass}")
+ "[$name] $operation $key=$value, unknown type: ${value?.javaClass}",
+ )
}
}
}
@@ -191,14 +211,31 @@
}
companion object {
- private fun Context.getSharedPreferencesFilePath(name: String): String {
- val file = getSharedPreferencesFile(name)
- return file.relativeTo(dataDirCompat).toString()
+ /** Returns the storage object of default [SharedPreferences]. */
+ @JvmStatic
+ fun getDefault(context: Context, name: String): SharedPreferencesStorage {
+ val prefName = getDefaultSharedPreferencesName(context)
+ return SharedPreferencesStorage(
+ context,
+ name,
+ context.getSharedPreferences(prefName, Context.MODE_PRIVATE),
+ getSharedPreferencesFilePath(context, prefName),
+ )
+ }
+
+ /** Returns the name of default [SharedPreferences]. */
+ @JvmStatic
+ fun getDefaultSharedPreferencesName(context: Context) = context.packageName + "_preferences"
+
+ /** Returns the shared preferences file path relative to data dir. */
+ @JvmStatic
+ fun getSharedPreferencesFilePath(context: Context, name: String): String {
+ val file = context.getSharedPreferencesFile(name)
+ return file.relativeTo(context.dataDirCompat).toString()
}
/** Returns the absolute path of shared preferences file. */
- @JvmStatic
- fun Context.getSharedPreferencesFile(name: String): File {
+ private fun Context.getSharedPreferencesFile(name: String): File {
// ContextImpl.getSharedPreferencesPath is private
return File(getSharedPreferencesDir(), "$name.xml")
}
diff --git a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/KeyedObserverTest.kt b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/KeyedObserverTest.kt
index 0fdecb0..c99d4b3 100644
--- a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/KeyedObserverTest.kt
+++ b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/KeyedObserverTest.kt
@@ -45,14 +45,14 @@
@Test
fun addObserver_sameExecutor() {
- keyedObservable.addObserver(observer1, executor1)
- keyedObservable.addObserver(observer1, executor1)
+ assertThat(keyedObservable.addObserver(observer1, executor1)).isTrue()
+ assertThat(keyedObservable.addObserver(observer1, executor1)).isFalse()
}
@Test
fun addObserver_keyedObserver_sameExecutor() {
- keyedObservable.addObserver(key1, keyedObserver1, executor1)
- keyedObservable.addObserver(key1, keyedObserver1, executor1)
+ assertThat(keyedObservable.addObserver(key1, keyedObserver1, executor1)).isTrue()
+ assertThat(keyedObservable.addObserver(key1, keyedObserver1, executor1)).isFalse()
}
@Test
@@ -109,15 +109,15 @@
@Test
fun addObserver_notifyObservers_removeObserver() {
- keyedObservable.addObserver(observer1, executor1)
- keyedObservable.addObserver(observer2, executor2)
+ assertThat(keyedObservable.addObserver(observer1, executor1)).isTrue()
+ assertThat(keyedObservable.addObserver(observer2, executor2)).isTrue()
keyedObservable.notifyChange(DataChangeReason.UPDATE)
verify(observer1).onKeyChanged(null, DataChangeReason.UPDATE)
verify(observer2).onKeyChanged(null, DataChangeReason.UPDATE)
reset(observer1, observer2)
- keyedObservable.removeObserver(observer2)
+ assertThat(keyedObservable.removeObserver(observer2)).isTrue()
keyedObservable.notifyChange(DataChangeReason.DELETE)
verify(observer1).onKeyChanged(null, DataChangeReason.DELETE)
@@ -126,15 +126,15 @@
@Test
fun addObserver_keyedObserver_notifyObservers_removeObserver() {
- keyedObservable.addObserver(key1, keyedObserver1, executor1)
- keyedObservable.addObserver(key2, keyedObserver2, executor2)
+ assertThat(keyedObservable.addObserver(key1, keyedObserver1, executor1)).isTrue()
+ assertThat(keyedObservable.addObserver(key2, keyedObserver2, executor2)).isTrue()
keyedObservable.notifyChange(key1, DataChangeReason.UPDATE)
verify(keyedObserver1).onKeyChanged(key1, DataChangeReason.UPDATE)
verify(keyedObserver2, never()).onKeyChanged(key2, DataChangeReason.UPDATE)
reset(keyedObserver1, keyedObserver2)
- keyedObservable.removeObserver(key1, keyedObserver1)
+ assertThat(keyedObservable.removeObserver(key1, keyedObserver1)).isTrue()
keyedObservable.notifyChange(key1, DataChangeReason.DELETE)
verify(keyedObserver1, never()).onKeyChanged(key1, DataChangeReason.DELETE)
@@ -143,9 +143,9 @@
@Test
fun notifyChange_addMoreTypeObservers_checkOnKeyChanged() {
- keyedObservable.addObserver(observer1, executor1)
- keyedObservable.addObserver(key1, keyedObserver1, executor1)
- keyedObservable.addObserver(key2, keyedObserver2, executor1)
+ assertThat(keyedObservable.addObserver(observer1, executor1)).isTrue()
+ assertThat(keyedObservable.addObserver(key1, keyedObserver1, executor1)).isTrue()
+ assertThat(keyedObservable.addObserver(key2, keyedObserver2, executor1)).isTrue()
keyedObservable.notifyChange(DataChangeReason.UPDATE)
verify(observer1).onKeyChanged(null, DataChangeReason.UPDATE)
@@ -171,25 +171,25 @@
fun notifyChange_addObserverWithinCallback() {
// ConcurrentModificationException is raised if it is not implemented correctly
val observer: KeyedObserver<Any?> = KeyedObserver { _, _ ->
- keyedObservable.addObserver(observer1, executor1)
+ assertThat(keyedObservable.addObserver(observer1, executor1)).isTrue()
}
- keyedObservable.addObserver(observer, executor1)
+ assertThat(keyedObservable.addObserver(observer, executor1)).isTrue()
keyedObservable.notifyChange(DataChangeReason.UPDATE)
- keyedObservable.removeObserver(observer)
+ assertThat(keyedObservable.removeObserver(observer)).isTrue()
}
@Test
fun notifyChange_KeyedObserver_addObserverWithinCallback() {
// ConcurrentModificationException is raised if it is not implemented correctly
val keyObserver: KeyedObserver<Any?> = KeyedObserver { _, _ ->
- keyedObservable.addObserver(key1, keyedObserver1, executor1)
+ assertThat(keyedObservable.addObserver(key1, keyedObserver1, executor1)).isTrue()
}
- keyedObservable.addObserver(key1, keyObserver, executor1)
+ assertThat(keyedObservable.addObserver(key1, keyObserver, executor1)).isTrue()
keyedObservable.notifyChange(key1, DataChangeReason.UPDATE)
- keyedObservable.removeObserver(key1, keyObserver)
+ assertThat(keyedObservable.removeObserver(key1, keyObserver)).isTrue()
}
}
diff --git a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
index 4387b6f..a0599bb 100644
--- a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
+++ b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
@@ -35,6 +35,7 @@
import android.widget.FrameLayout;
import android.widget.ImageView;
+import androidx.annotation.Nullable;
import androidx.annotation.RawRes;
import androidx.annotation.StringRes;
import androidx.preference.Preference;
@@ -243,6 +244,14 @@
}
/**
+ * Gets the content description set by {@link #setContentDescription}.
+ */
+ @Nullable
+ public CharSequence getContentDescription() {
+ return mContentDescription;
+ }
+
+ /**
* Gets the lottie illustration resource id.
*/
public int getLottieAnimationResId() {
diff --git a/packages/SettingsLib/Metadata/Android.bp b/packages/SettingsLib/Metadata/Android.bp
new file mode 100644
index 0000000..207637f
--- /dev/null
+++ b/packages/SettingsLib/Metadata/Android.bp
@@ -0,0 +1,23 @@
+package {
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+filegroup {
+ name: "SettingsLibMetadata-srcs",
+ srcs: ["src/**/*.kt"],
+}
+
+android_library {
+ name: "SettingsLibMetadata",
+ defaults: [
+ "SettingsLintDefaults",
+ ],
+ srcs: [":SettingsLibMetadata-srcs"],
+ static_libs: [
+ "androidx.annotation_annotation",
+ "androidx.fragment_fragment",
+ "guava",
+ "SettingsLibDataStore",
+ ],
+ kotlincflags: ["-Xjvm-default=all"],
+}
diff --git a/packages/SettingsLib/Metadata/AndroidManifest.xml b/packages/SettingsLib/Metadata/AndroidManifest.xml
new file mode 100644
index 0000000..1c801e6
--- /dev/null
+++ b/packages/SettingsLib/Metadata/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.settingslib.metadata">
+
+ <uses-sdk android:minSdkVersion="21" />
+</manifest>
diff --git a/packages/SettingsLib/Metadata/processor/Android.bp b/packages/SettingsLib/Metadata/processor/Android.bp
new file mode 100644
index 0000000..d8acc76
--- /dev/null
+++ b/packages/SettingsLib/Metadata/processor/Android.bp
@@ -0,0 +1,11 @@
+package {
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+java_plugin {
+ name: "SettingsLibMetadata-processor",
+ srcs: ["src/**/*.kt"],
+ processor_class: "com.android.settingslib.metadata.PreferenceScreenAnnotationProcessor",
+ java_resource_dirs: ["resources"],
+ visibility: ["//visibility:public"],
+}
diff --git a/packages/SettingsLib/Metadata/processor/resources/META-INF/services/javax.annotation.processing.Processor b/packages/SettingsLib/Metadata/processor/resources/META-INF/services/javax.annotation.processing.Processor
new file mode 100644
index 0000000..762a01a
--- /dev/null
+++ b/packages/SettingsLib/Metadata/processor/resources/META-INF/services/javax.annotation.processing.Processor
@@ -0,0 +1 @@
+com.android.settingslib.metadata.PreferenceScreenAnnotationProcessor
\ No newline at end of file
diff --git a/packages/SettingsLib/Metadata/processor/src/com/android/settingslib/metadata/PreferenceScreenAnnotationProcessor.kt b/packages/SettingsLib/Metadata/processor/src/com/android/settingslib/metadata/PreferenceScreenAnnotationProcessor.kt
new file mode 100644
index 0000000..620d717
--- /dev/null
+++ b/packages/SettingsLib/Metadata/processor/src/com/android/settingslib/metadata/PreferenceScreenAnnotationProcessor.kt
@@ -0,0 +1,226 @@
+/*
+ * 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.settingslib.metadata
+
+import java.util.TreeMap
+import javax.annotation.processing.AbstractProcessor
+import javax.annotation.processing.ProcessingEnvironment
+import javax.annotation.processing.RoundEnvironment
+import javax.lang.model.SourceVersion
+import javax.lang.model.element.AnnotationMirror
+import javax.lang.model.element.AnnotationValue
+import javax.lang.model.element.Element
+import javax.lang.model.element.ElementKind
+import javax.lang.model.element.ExecutableElement
+import javax.lang.model.element.Modifier
+import javax.lang.model.element.TypeElement
+import javax.lang.model.type.TypeMirror
+import javax.tools.Diagnostic
+
+/** Processor to gather preference screens annotated with `@ProvidePreferenceScreen`. */
+class PreferenceScreenAnnotationProcessor : AbstractProcessor() {
+ private val screens = TreeMap<String, ConstructorType>()
+ private val overlays = mutableMapOf<String, String>()
+ private val contextType: TypeMirror by lazy {
+ processingEnv.elementUtils.getTypeElement("android.content.Context").asType()
+ }
+
+ private var options: Map<String, Any?>? = null
+ private lateinit var annotationElement: TypeElement
+ private lateinit var optionsElement: TypeElement
+ private lateinit var screenType: TypeMirror
+
+ override fun getSupportedAnnotationTypes() = setOf(ANNOTATION, OPTIONS)
+
+ override fun getSupportedSourceVersion(): SourceVersion = SourceVersion.latestSupported()
+
+ override fun init(processingEnv: ProcessingEnvironment) {
+ super.init(processingEnv)
+ val elementUtils = processingEnv.elementUtils
+ annotationElement = elementUtils.getTypeElement(ANNOTATION)
+ optionsElement = elementUtils.getTypeElement(OPTIONS)
+ screenType = elementUtils.getTypeElement("$PACKAGE.$PREFERENCE_SCREEN_METADATA").asType()
+ }
+
+ override fun process(
+ annotations: MutableSet<out TypeElement>,
+ roundEnv: RoundEnvironment,
+ ): Boolean {
+ roundEnv.getElementsAnnotatedWith(optionsElement).singleOrNull()?.run {
+ if (options != null) error("@$OPTIONS_NAME is already specified: $options", this)
+ options =
+ annotationMirrors
+ .single { it.isElement(optionsElement) }
+ .elementValues
+ .entries
+ .associate { it.key.simpleName.toString() to it.value.value }
+ }
+ for (element in roundEnv.getElementsAnnotatedWith(annotationElement)) {
+ (element as? TypeElement)?.process()
+ }
+ if (roundEnv.processingOver()) codegen()
+ return false
+ }
+
+ private fun TypeElement.process() {
+ if (kind != ElementKind.CLASS || modifiers.contains(Modifier.ABSTRACT)) {
+ error("@$ANNOTATION_NAME must be added to non abstract class", this)
+ return
+ }
+ if (!processingEnv.typeUtils.isAssignable(asType(), screenType)) {
+ error("@$ANNOTATION_NAME must be added to $PREFERENCE_SCREEN_METADATA subclass", this)
+ return
+ }
+ val constructorType = getConstructorType()
+ if (constructorType == null) {
+ error(
+ "Class must be an object, or has single public constructor that " +
+ "accepts no parameter or a Context parameter",
+ this,
+ )
+ return
+ }
+ val screenQualifiedName = qualifiedName.toString()
+ screens[screenQualifiedName] = constructorType
+ val annotation = annotationMirrors.single { it.isElement(annotationElement) }
+ val overlay = annotation.getOverlay()
+ if (overlay != null) {
+ overlays.put(overlay, screenQualifiedName)?.let {
+ error("$overlay has been overlaid by $it", this)
+ }
+ }
+ }
+
+ private fun codegen() {
+ val collector = (options?.get("codegenCollector") as? String) ?: DEFAULT_COLLECTOR
+ if (collector.isEmpty()) return
+ val parts = collector.split('/')
+ if (parts.size == 3) {
+ generateCode(parts[0], parts[1], parts[2])
+ } else {
+ throw IllegalArgumentException(
+ "Collector option '$collector' does not follow 'PKG/CLASS/METHOD' format"
+ )
+ }
+ }
+
+ private fun generateCode(outputPkg: String, outputClass: String, outputFun: String) {
+ for ((overlay, screen) in overlays) {
+ if (screens.remove(overlay) == null) {
+ warn("$overlay is overlaid by $screen but not annotated with @$ANNOTATION_NAME")
+ } else {
+ processingEnv.messager.printMessage(
+ Diagnostic.Kind.NOTE,
+ "$overlay is overlaid by $screen",
+ )
+ }
+ }
+ processingEnv.filer.createSourceFile("$outputPkg.$outputClass").openWriter().use {
+ it.write("package $outputPkg;\n\n")
+ it.write("import $PACKAGE.$PREFERENCE_SCREEN_METADATA;\n\n")
+ it.write("// Generated by annotation processor for @$ANNOTATION_NAME\n")
+ it.write("public final class $outputClass {\n")
+ it.write(" private $outputClass() {}\n\n")
+ it.write(
+ " public static java.util.List<$PREFERENCE_SCREEN_METADATA> " +
+ "$outputFun(android.content.Context context) {\n"
+ )
+ it.write(
+ " java.util.ArrayList<$PREFERENCE_SCREEN_METADATA> screens = " +
+ "new java.util.ArrayList<>(${screens.size});\n"
+ )
+ for ((screen, constructorType) in screens) {
+ when (constructorType) {
+ ConstructorType.DEFAULT -> it.write(" screens.add(new $screen());\n")
+ ConstructorType.CONTEXT -> it.write(" screens.add(new $screen(context));\n")
+ ConstructorType.SINGLETON -> it.write(" screens.add($screen.INSTANCE);\n")
+ }
+ }
+ for ((overlay, screen) in overlays) {
+ it.write(" // $overlay is overlaid by $screen\n")
+ }
+ it.write(" return screens;\n")
+ it.write(" }\n")
+ it.write("}")
+ }
+ }
+
+ private fun AnnotationMirror.isElement(element: TypeElement) =
+ processingEnv.typeUtils.isSameType(annotationType.asElement().asType(), element.asType())
+
+ private fun AnnotationMirror.getOverlay(): String? {
+ for ((key, value) in elementValues) {
+ if (key.simpleName.contentEquals("overlay")) {
+ return if (value.isDefaultClassValue(key)) null else value.value.toString()
+ }
+ }
+ return null
+ }
+
+ private fun AnnotationValue.isDefaultClassValue(key: ExecutableElement) =
+ processingEnv.typeUtils.isSameType(
+ value as TypeMirror,
+ key.defaultValue.value as TypeMirror,
+ )
+
+ private fun TypeElement.getConstructorType(): ConstructorType? {
+ var constructor: ExecutableElement? = null
+ for (element in enclosedElements) {
+ if (element.isKotlinObject()) return ConstructorType.SINGLETON
+ if (element.kind != ElementKind.CONSTRUCTOR) continue
+ if (!element.modifiers.contains(Modifier.PUBLIC)) continue
+ if (constructor != null) return null
+ constructor = element as ExecutableElement
+ }
+ return constructor?.parameters?.run {
+ when {
+ isEmpty() -> ConstructorType.DEFAULT
+ size == 1 && processingEnv.typeUtils.isSameType(this[0].asType(), contextType) ->
+ ConstructorType.CONTEXT
+ else -> null
+ }
+ }
+ }
+
+ private fun Element.isKotlinObject() =
+ kind == ElementKind.FIELD &&
+ modifiers.run { contains(Modifier.PUBLIC) && contains(Modifier.STATIC) } &&
+ simpleName.toString() == "INSTANCE"
+
+ private fun warn(msg: CharSequence) =
+ processingEnv.messager.printMessage(Diagnostic.Kind.WARNING, msg)
+
+ private fun error(msg: CharSequence, element: Element) =
+ processingEnv.messager.printMessage(Diagnostic.Kind.ERROR, msg, element)
+
+ private enum class ConstructorType {
+ DEFAULT, // default constructor with no parameter
+ CONTEXT, // constructor with a Context parameter
+ SINGLETON, // Kotlin object class
+ }
+
+ companion object {
+ private const val PACKAGE = "com.android.settingslib.metadata"
+ private const val ANNOTATION_NAME = "ProvidePreferenceScreen"
+ private const val ANNOTATION = "$PACKAGE.$ANNOTATION_NAME"
+ private const val PREFERENCE_SCREEN_METADATA = "PreferenceScreenMetadata"
+
+ private const val OPTIONS_NAME = "ProvidePreferenceScreenOptions"
+ private const val OPTIONS = "$PACKAGE.$OPTIONS_NAME"
+ private const val DEFAULT_COLLECTOR = "$PACKAGE/PreferenceScreenCollector/get"
+ }
+}
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/Annotations.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/Annotations.kt
new file mode 100644
index 0000000..ea20a74
--- /dev/null
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/Annotations.kt
@@ -0,0 +1,49 @@
+/*
+ * 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.settingslib.metadata
+
+import kotlin.reflect.KClass
+
+/**
+ * Annotation to provide preference screen.
+ *
+ * The annotated class must satisfy either condition:
+ * - the primary constructor has no parameter
+ * - the primary constructor has a single [android.content.Context] parameter
+ * - it is a Kotlin object class
+ *
+ * @param overlay if specified, current annotated screen will overlay the given screen
+ */
+@Retention(AnnotationRetention.SOURCE)
+@Target(AnnotationTarget.CLASS)
+@MustBeDocumented
+annotation class ProvidePreferenceScreen(
+ val overlay: KClass<out PreferenceScreenMetadata> = PreferenceScreenMetadata::class,
+)
+
+/**
+ * Provides options for [ProvidePreferenceScreen] annotation processor.
+ *
+ * @param codegenCollector generated collector class (format: "pkg/class/method"), an empty string
+ * means do not generate code
+ */
+@Retention(AnnotationRetention.SOURCE)
+@Target(AnnotationTarget.CLASS)
+@MustBeDocumented
+annotation class ProvidePreferenceScreenOptions(
+ val codegenCollector: String = "com.android.settingslib.metadata/PreferenceScreenCollector/get",
+)
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PersistentPreference.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PersistentPreference.kt
new file mode 100644
index 0000000..51a8580
--- /dev/null
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PersistentPreference.kt
@@ -0,0 +1,174 @@
+/*
+ * 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.settingslib.metadata
+
+import android.content.Context
+import androidx.annotation.ArrayRes
+import androidx.annotation.IntDef
+import com.android.settingslib.datastore.KeyValueStore
+
+/** Permit of read and write request. */
+@IntDef(
+ ReadWritePermit.ALLOW,
+ ReadWritePermit.DISALLOW,
+ ReadWritePermit.REQUIRE_APP_PERMISSION,
+ ReadWritePermit.REQUIRE_USER_AGREEMENT,
+)
+@Retention(AnnotationRetention.SOURCE)
+annotation class ReadWritePermit {
+ companion object {
+ /** Allow to read/write value. */
+ const val ALLOW = 0
+ /** Disallow to read/write value (e.g. uid not allowed). */
+ const val DISALLOW = 1
+ /** Require (runtime/special) app permission from user explicitly. */
+ const val REQUIRE_APP_PERMISSION = 2
+ /** Require explicit user agreement (e.g. terms of service). */
+ const val REQUIRE_USER_AGREEMENT = 3
+ }
+}
+
+/** Preference interface that has a value persisted in datastore. */
+interface PersistentPreference<T> {
+
+ /**
+ * Returns the key-value storage of the preference.
+ *
+ * The default implementation returns the storage provided by
+ * [PreferenceScreenRegistry.getKeyValueStore].
+ */
+ fun storage(context: Context): KeyValueStore =
+ PreferenceScreenRegistry.getKeyValueStore(context, this as PreferenceMetadata)!!
+
+ /**
+ * Returns if the external application (identified by [callingUid]) has permission to read
+ * preference value.
+ *
+ * The underlying implementation does NOT need to check common states like isEnabled,
+ * isRestricted or isAvailable.
+ */
+ @ReadWritePermit
+ fun getReadPermit(context: Context, myUid: Int, callingUid: Int): Int =
+ PreferenceScreenRegistry.getReadPermit(
+ context,
+ myUid,
+ callingUid,
+ this as PreferenceMetadata,
+ )
+
+ /**
+ * Returns if the external application (identified by [callingUid]) has permission to write
+ * preference with given [value].
+ *
+ * The underlying implementation does NOT need to check common states like isEnabled,
+ * isRestricted or isAvailable.
+ */
+ @ReadWritePermit
+ fun getWritePermit(context: Context, value: T?, myUid: Int, callingUid: Int): Int =
+ PreferenceScreenRegistry.getWritePermit(
+ context,
+ value,
+ myUid,
+ callingUid,
+ this as PreferenceMetadata,
+ )
+}
+
+/** Descriptor of values. */
+sealed interface ValueDescriptor {
+
+ /** Returns if given value (represented by index) is valid. */
+ fun isValidValue(context: Context, index: Int): Boolean
+}
+
+/**
+ * A boolean type value.
+ *
+ * A zero value means `False`, otherwise it is `True`.
+ */
+interface BooleanValue : ValueDescriptor {
+ override fun isValidValue(context: Context, index: Int) = true
+}
+
+/** Value falls into a given array. */
+interface DiscreteValue<T> : ValueDescriptor {
+ @get:ArrayRes val values: Int
+
+ @get:ArrayRes val valuesDescription: Int
+
+ fun getValue(context: Context, index: Int): T
+}
+
+/**
+ * Value falls into a text array, whose element is [CharSequence] type.
+ *
+ * [values] resource is `<string-array>`.
+ */
+interface DiscreteTextValue : DiscreteValue<CharSequence> {
+ override fun isValidValue(context: Context, index: Int): Boolean {
+ if (index < 0) return false
+ return index < context.resources.getTextArray(values).size
+ }
+
+ override fun getValue(context: Context, index: Int): CharSequence =
+ context.resources.getTextArray(values)[index]
+}
+
+/**
+ * Value falls into a string array, whose element is [String] type.
+ *
+ * [values] resource is `<string-array>`.
+ */
+interface DiscreteStringValue : DiscreteValue<String> {
+ override fun isValidValue(context: Context, index: Int): Boolean {
+ if (index < 0) return false
+ return index < context.resources.getStringArray(values).size
+ }
+
+ override fun getValue(context: Context, index: Int): String =
+ context.resources.getStringArray(values)[index]
+}
+
+/**
+ * Value falls into an integer array.
+ *
+ * [values] resource is `<integer-array>`.
+ */
+interface DiscreteIntValue : DiscreteValue<Int> {
+ override fun isValidValue(context: Context, index: Int): Boolean {
+ if (index < 0) return false
+ return index < context.resources.getIntArray(values).size
+ }
+
+ override fun getValue(context: Context, index: Int): Int =
+ context.resources.getIntArray(values)[index]
+}
+
+/** Value is between a range. */
+interface RangeValue : ValueDescriptor {
+ /** The lower bound (inclusive) of the range. */
+ val minValue: Int
+
+ /** The upper bound (inclusive) of the range. */
+ val maxValue: Int
+
+ /** The increment step within the range. 0 means unset, which implies step size is 1. */
+ val incrementStep: Int
+ get() = 0
+
+ override fun isValidValue(context: Context, index: Int) = index in minValue..maxValue
+}
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceHierarchy.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceHierarchy.kt
new file mode 100644
index 0000000..4503738
--- /dev/null
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceHierarchy.kt
@@ -0,0 +1,127 @@
+/*
+ * 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.settingslib.metadata
+
+/** A node in preference hierarchy that is associated with [PreferenceMetadata]. */
+open class PreferenceHierarchyNode internal constructor(val metadata: PreferenceMetadata)
+
+/**
+ * Preference hierarchy describes the structure of preferences recursively.
+ *
+ * A root hierarchy represents a preference screen. A sub-hierarchy represents a preference group.
+ */
+class PreferenceHierarchy internal constructor(metadata: PreferenceMetadata) :
+ PreferenceHierarchyNode(metadata) {
+
+ private val children = mutableListOf<PreferenceHierarchyNode>()
+
+ /** Adds a preference to the hierarchy. */
+ operator fun PreferenceMetadata.unaryPlus() {
+ children.add(PreferenceHierarchyNode(this))
+ }
+
+ /**
+ * Adds preference screen with given key (as a placeholder) to the hierarchy.
+ *
+ * This is mainly to support Android Settings overlays. OEMs might want to custom some of the
+ * screens. In resource-based hierarchy, it leverages the resource overlay. In terms of DSL or
+ * programmatic hierarchy, it will be a problem to specify concrete screen metadata objects.
+ * Instead, use preference screen key as a placeholder in the hierarchy and screen metadata will
+ * be looked up from [PreferenceScreenRegistry] lazily at runtime.
+ *
+ * @throws NullPointerException if screen is not registered to [PreferenceScreenRegistry]
+ */
+ operator fun String.unaryPlus() {
+ children.add(PreferenceHierarchyNode(PreferenceScreenRegistry[this]!!))
+ }
+
+ /** Adds a preference to the hierarchy. */
+ fun add(metadata: PreferenceMetadata) {
+ children.add(PreferenceHierarchyNode(metadata))
+ }
+
+ /** Adds a preference group to the hierarchy. */
+ operator fun PreferenceGroup.unaryPlus() = PreferenceHierarchy(this).also { children.add(it) }
+
+ /** Adds a preference group and returns its preference hierarchy. */
+ fun addGroup(metadata: PreferenceGroup): PreferenceHierarchy =
+ PreferenceHierarchy(metadata).also { children.add(it) }
+
+ /**
+ * Adds preference screen with given key (as a placeholder) to the hierarchy.
+ *
+ * This is mainly to support Android Settings overlays. OEMs might want to custom some of the
+ * screens. In resource-based hierarchy, it leverages the resource overlay. In terms of DSL or
+ * programmatic hierarchy, it will be a problem to specify concrete screen metadata objects.
+ * Instead, use preference screen key as a placeholder in the hierarchy and screen metadata will
+ * be looked up from [PreferenceScreenRegistry] lazily at runtime.
+ *
+ * @throws NullPointerException if screen is not registered to [PreferenceScreenRegistry]
+ */
+ fun addPreferenceScreen(screenKey: String) {
+ children.add(PreferenceHierarchy(PreferenceScreenRegistry[screenKey]!!))
+ }
+
+ /** Extensions to add more preferences to the hierarchy. */
+ operator fun plusAssign(init: PreferenceHierarchy.() -> Unit) = init(this)
+
+ /** Traversals preference hierarchy and applies given action. */
+ fun forEach(action: (PreferenceHierarchyNode) -> Unit) {
+ for (it in children) action(it)
+ }
+
+ /** Traversals preference hierarchy and applies given action. */
+ suspend fun forEachAsync(action: suspend (PreferenceHierarchyNode) -> Unit) {
+ for (it in children) action(it)
+ }
+
+ /** Finds the [PreferenceMetadata] object associated with given key. */
+ fun find(key: String): PreferenceMetadata? {
+ if (metadata.key == key) return metadata
+ for (child in children) {
+ if (child is PreferenceHierarchy) {
+ val result = child.find(key)
+ if (result != null) return result
+ } else {
+ if (child.metadata.key == key) return child.metadata
+ }
+ }
+ return null
+ }
+
+ /** Returns all the [PreferenceMetadata]s appear in the hierarchy. */
+ fun getAllPreferences(): List<PreferenceMetadata> =
+ mutableListOf<PreferenceMetadata>().also { getAllPreferences(it) }
+
+ private fun getAllPreferences(result: MutableList<PreferenceMetadata>) {
+ result.add(metadata)
+ for (child in children) {
+ if (child is PreferenceHierarchy) {
+ child.getAllPreferences(result)
+ } else {
+ result.add(child.metadata)
+ }
+ }
+ }
+}
+
+/**
+ * Builder function to create [PreferenceHierarchy] in
+ * [DSL](https://kotlinlang.org/docs/type-safe-builders.html) manner.
+ */
+fun preferenceHierarchy(metadata: PreferenceMetadata, init: PreferenceHierarchy.() -> Unit) =
+ PreferenceHierarchy(metadata).also(init)
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceMetadata.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceMetadata.kt
new file mode 100644
index 0000000..f39f3a0
--- /dev/null
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceMetadata.kt
@@ -0,0 +1,204 @@
+/*
+ * 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.settingslib.metadata
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import androidx.annotation.AnyThread
+import androidx.annotation.DrawableRes
+import androidx.annotation.StringRes
+
+/**
+ * Interface provides preference metadata (title, summary, icon, etc.).
+ *
+ * Besides the existing APIs, subclass could integrate with following interface to provide more
+ * information:
+ * - [PreferenceTitleProvider]: provide dynamic title content
+ * - [PreferenceSummaryProvider]: provide dynamic summary content (e.g. based on preference value)
+ * - [PreferenceAvailabilityProvider]: provide preference availability (e.g. based on flag)
+ * - [PreferenceLifecycleProvider]: provide the lifecycle callbacks and notify state change
+ *
+ * Notes:
+ * - UI framework support:
+ * - This class does not involve any UI logic, it is the data layer.
+ * - Subclass could integrate with datastore and UI widget to provide UI layer. For instance,
+ * `PreferenceBinding` supports Jetpack Preference binding.
+ * - Datastore:
+ * - Subclass should implement the [PersistentPreference] to note that current preference is
+ * persistent in datastore.
+ * - It is always recommended to support back up preference value changed by user. Typically,
+ * the back up and restore happen within datastore, the [allowBackup] API is to mark if
+ * current preference value should be backed up (backup allowed by default).
+ * - Preference indexing for search:
+ * - Override [isIndexable] API to mark if preference is indexable (enabled by default).
+ * - If [isIndexable] returns true, preference title and summary will be indexed with cache.
+ * More indexing data could be provided through [keywords].
+ * - Settings search will cache the preference title/summary/keywords for indexing. The cache is
+ * invalidated when system locale changed, app upgraded, etc.
+ * - Dynamic content is not suitable to be cached for indexing. Subclass that implements
+ * [PreferenceTitleProvider] / [PreferenceSummaryProvider] will not have its title / summary
+ * indexed.
+ */
+@AnyThread
+interface PreferenceMetadata {
+
+ /** Preference key. */
+ val key: String
+
+ /**
+ * Preference title resource id.
+ *
+ * Implement [PreferenceTitleProvider] if title is generated dynamically.
+ */
+ val title: Int
+ @StringRes get() = 0
+
+ /**
+ * Preference summary resource id.
+ *
+ * Implement [PreferenceSummaryProvider] if summary is generated dynamically (e.g. summary is
+ * provided per preference value)
+ */
+ val summary: Int
+ @StringRes get() = 0
+
+ /** Icon of the preference. */
+ val icon: Int
+ @DrawableRes get() = 0
+
+ /** Additional keywords for indexing. */
+ val keywords: Int
+ @StringRes get() = 0
+
+ /**
+ * Return the extras Bundle object associated with this preference.
+ *
+ * It is used to provide more information for metadata.
+ */
+ fun extras(context: Context): Bundle? = null
+
+ /**
+ * Returns if preference is indexable, default value is `true`.
+ *
+ * Return `false` only when the preference is always unavailable on current device. If it is
+ * conditional available, override [PreferenceAvailabilityProvider].
+ */
+ fun isIndexable(context: Context): Boolean = true
+
+ /**
+ * Returns if preference is enabled.
+ *
+ * UI framework normally does not allow user to interact with the preference widget when it is
+ * disabled.
+ *
+ * [dependencyOfEnabledState] is provided to support dependency, the [shouldDisableDependents]
+ * value of dependent preference is used to decide enabled state.
+ */
+ fun isEnabled(context: Context): Boolean {
+ val dependency = dependencyOfEnabledState(context) ?: return true
+ return !dependency.shouldDisableDependents(context)
+ }
+
+ /** Returns the key of depended preference to decide the enabled state. */
+ fun dependencyOfEnabledState(context: Context): PreferenceMetadata? = null
+
+ /** Returns whether this preference's dependents should be disabled. */
+ fun shouldDisableDependents(context: Context): Boolean = !isEnabled(context)
+
+ /** Returns if the preference is persistent in datastore. */
+ fun isPersistent(context: Context): Boolean = this is PersistentPreference<*>
+
+ /**
+ * Returns if preference value backup is allowed (by default returns `true` if preference is
+ * persistent).
+ */
+ fun allowBackup(context: Context): Boolean = isPersistent(context)
+
+ /** Returns preference intent. */
+ fun intent(context: Context): Intent? = null
+
+ /** Returns preference order. */
+ fun order(context: Context): Int? = null
+
+ /**
+ * Returns the preference title.
+ *
+ * Implement [PreferenceTitleProvider] interface if title content is generated dynamically.
+ */
+ fun getPreferenceTitle(context: Context): CharSequence? =
+ when {
+ title != 0 -> context.getText(title)
+ this is PreferenceTitleProvider -> getTitle(context)
+ else -> null
+ }
+
+ /**
+ * Returns the preference summary.
+ *
+ * Implement [PreferenceSummaryProvider] interface if summary content is generated dynamically
+ * (e.g. summary is provided per preference value).
+ */
+ fun getPreferenceSummary(context: Context): CharSequence? =
+ when {
+ summary != 0 -> context.getText(summary)
+ this is PreferenceSummaryProvider -> getSummary(context)
+ else -> null
+ }
+}
+
+/** Metadata of preference group. */
+@AnyThread
+open class PreferenceGroup(override val key: String, override val title: Int) : PreferenceMetadata
+
+/** Metadata of preference screen. */
+@AnyThread
+interface PreferenceScreenMetadata : PreferenceMetadata {
+
+ /**
+ * The screen title resource, which precedes [getScreenTitle] if provided.
+ *
+ * By default, screen title is same with [title].
+ */
+ val screenTitle: Int
+ get() = title
+
+ /** Returns dynamic screen title, use [screenTitle] whenever possible. */
+ fun getScreenTitle(context: Context): CharSequence? = null
+
+ /** Returns the fragment class to show the preference screen. */
+ fun fragmentClass(): Class<out Fragment>?
+
+ /**
+ * Indicates if [getPreferenceHierarchy] returns a complete hierarchy of the preference screen.
+ *
+ * If `true`, the result of [getPreferenceHierarchy] will be used to inflate preference screen.
+ * Otherwise, it is an intermediate state called hybrid mode, preference hierarchy is
+ * represented by other ways (e.g. XML resource) and [PreferenceMetadata]s in
+ * [getPreferenceHierarchy] will only be used to bind UI widgets.
+ */
+ fun hasCompleteHierarchy(): Boolean = true
+
+ /**
+ * Returns the hierarchy of preference screen.
+ *
+ * The implementation MUST include all preferences into the hierarchy regardless of the runtime
+ * conditions. DO NOT check any condition (except compile time flag) before adding a preference.
+ */
+ fun getPreferenceHierarchy(context: Context): PreferenceHierarchy
+}
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceScreenBindingKeyProvider.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceScreenBindingKeyProvider.kt
new file mode 100644
index 0000000..84014f1
--- /dev/null
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceScreenBindingKeyProvider.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.settingslib.metadata
+
+import android.content.Context
+
+/** Provides the associated preference screen key for binding. */
+interface PreferenceScreenBindingKeyProvider {
+
+ /** Returns the associated preference screen key. */
+ fun getPreferenceScreenBindingKey(context: Context): String?
+}
+
+/** Extra key to provide the preference screen key for binding. */
+const val EXTRA_BINDING_SCREEN_KEY = "settingslib:binding_screen_key"
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceScreenRegistry.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceScreenRegistry.kt
new file mode 100644
index 0000000..48798da
--- /dev/null
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceScreenRegistry.kt
@@ -0,0 +1,157 @@
+/*
+ * 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.settingslib.metadata
+
+import android.content.Context
+import com.android.settingslib.datastore.KeyValueStore
+import com.google.common.base.Supplier
+import com.google.common.base.Suppliers
+import com.google.common.collect.ImmutableMap
+
+private typealias PreferenceScreenMap = ImmutableMap<String, PreferenceScreenMetadata>
+
+/** Registry of all available preference screens in the app. */
+object PreferenceScreenRegistry : ReadWritePermitProvider {
+
+ /** Provider of key-value store. */
+ private lateinit var keyValueStoreProvider: KeyValueStoreProvider
+
+ private var preferenceScreensSupplier: Supplier<PreferenceScreenMap> = Supplier {
+ ImmutableMap.of()
+ }
+
+ private val preferenceScreens: PreferenceScreenMap
+ get() = preferenceScreensSupplier.get()
+
+ private var readWritePermitProvider: ReadWritePermitProvider? = null
+
+ /** Sets the [KeyValueStoreProvider]. */
+ fun setKeyValueStoreProvider(keyValueStoreProvider: KeyValueStoreProvider) {
+ this.keyValueStoreProvider = keyValueStoreProvider
+ }
+
+ /**
+ * Returns the key-value store for given preference.
+ *
+ * Must call [setKeyValueStoreProvider] before invoking this method, otherwise
+ * [NullPointerException] is raised.
+ */
+ fun getKeyValueStore(context: Context, preference: PreferenceMetadata): KeyValueStore? =
+ keyValueStoreProvider.getKeyValueStore(context, preference)
+
+ /** Sets supplier to provide available preference screens. */
+ fun setPreferenceScreensSupplier(supplier: Supplier<List<PreferenceScreenMetadata>>) {
+ preferenceScreensSupplier =
+ Suppliers.memoize {
+ val screensBuilder = ImmutableMap.builder<String, PreferenceScreenMetadata>()
+ for (screen in supplier.get()) screensBuilder.put(screen.key, screen)
+ screensBuilder.buildOrThrow()
+ }
+ }
+
+ /** Sets available preference screens. */
+ fun setPreferenceScreens(vararg screens: PreferenceScreenMetadata) {
+ val screensBuilder = ImmutableMap.builder<String, PreferenceScreenMetadata>()
+ for (screen in screens) screensBuilder.put(screen.key, screen)
+ preferenceScreensSupplier = Suppliers.ofInstance(screensBuilder.buildOrThrow())
+ }
+
+ /** Returns [PreferenceScreenMetadata] of particular key. */
+ operator fun get(key: String?): PreferenceScreenMetadata? =
+ if (key != null) preferenceScreens[key] else null
+
+ /**
+ * Sets the provider to check read write permit. Read and write requests are denied by default.
+ */
+ fun setReadWritePermitProvider(readWritePermitProvider: ReadWritePermitProvider?) {
+ this.readWritePermitProvider = readWritePermitProvider
+ }
+
+ override fun getReadPermit(
+ context: Context,
+ myUid: Int,
+ callingUid: Int,
+ preference: PreferenceMetadata,
+ ) =
+ readWritePermitProvider?.getReadPermit(context, myUid, callingUid, preference)
+ ?: ReadWritePermit.DISALLOW
+
+ override fun getWritePermit(
+ context: Context,
+ value: Any?,
+ myUid: Int,
+ callingUid: Int,
+ preference: PreferenceMetadata,
+ ) =
+ readWritePermitProvider?.getWritePermit(context, value, myUid, callingUid, preference)
+ ?: ReadWritePermit.DISALLOW
+}
+
+/** Provider of [KeyValueStore]. */
+fun interface KeyValueStoreProvider {
+
+ /**
+ * Returns the key-value store for given preference.
+ *
+ * Here are some use cases:
+ * - provide the default storage for all preferences
+ * - determine the storage per preference keys or the interfaces implemented by the preference
+ */
+ fun getKeyValueStore(context: Context, preference: PreferenceMetadata): KeyValueStore?
+}
+
+/** Provider of read and write permit. */
+interface ReadWritePermitProvider {
+
+ @ReadWritePermit
+ fun getReadPermit(
+ context: Context,
+ myUid: Int,
+ callingUid: Int,
+ preference: PreferenceMetadata,
+ ): Int
+
+ @ReadWritePermit
+ fun getWritePermit(
+ context: Context,
+ value: Any?,
+ myUid: Int,
+ callingUid: Int,
+ preference: PreferenceMetadata,
+ ): Int
+
+ companion object {
+ @JvmField
+ val ALLOW_ALL_READ_WRITE =
+ object : ReadWritePermitProvider {
+ override fun getReadPermit(
+ context: Context,
+ myUid: Int,
+ callingUid: Int,
+ preference: PreferenceMetadata,
+ ) = ReadWritePermit.ALLOW
+
+ override fun getWritePermit(
+ context: Context,
+ value: Any?,
+ myUid: Int,
+ callingUid: Int,
+ preference: PreferenceMetadata,
+ ) = ReadWritePermit.ALLOW
+ }
+ }
+}
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceStateProviders.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceStateProviders.kt
new file mode 100644
index 0000000..a3aa85d
--- /dev/null
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceStateProviders.kt
@@ -0,0 +1,95 @@
+/*
+ * 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.settingslib.metadata
+
+import android.content.Context
+
+/**
+ * Interface to provide dynamic preference title.
+ *
+ * Implement this interface implies that the preference title should not be cached for indexing.
+ */
+interface PreferenceTitleProvider {
+
+ /** Provides preference title. */
+ fun getTitle(context: Context): CharSequence?
+}
+
+/**
+ * Interface to provide dynamic preference summary.
+ *
+ * Implement this interface implies that the preference summary should not be cached for indexing.
+ */
+interface PreferenceSummaryProvider {
+
+ /** Provides preference summary. */
+ fun getSummary(context: Context): CharSequence?
+}
+
+/**
+ * Interface to provide the state of preference availability.
+ *
+ * UI framework normally does not show the preference widget if it is unavailable.
+ */
+interface PreferenceAvailabilityProvider {
+
+ /** Returns if the preference is available. */
+ fun isAvailable(context: Context): Boolean
+}
+
+/**
+ * Interface to provide the managed configuration state of the preference.
+ *
+ * See [Managed configurations](https://developer.android.com/work/managed-configurations) for the
+ * Android Enterprise support.
+ */
+interface PreferenceRestrictionProvider {
+
+ /** Returns if preference is restricted by managed configs. */
+ fun isRestricted(context: Context): Boolean
+}
+
+/**
+ * Preference lifecycle to deal with preference state.
+ *
+ * Implement this interface when preference depends on runtime conditions.
+ */
+interface PreferenceLifecycleProvider {
+
+ /**
+ * Called when preference is attached to UI.
+ *
+ * Subclass could override this API to register runtime condition listeners, and invoke
+ * `onPreferenceStateChanged(this)` on the given [preferenceStateObserver] to update UI when
+ * internal state (e.g. availability, enabled state, title, summary) is changed.
+ */
+ fun onAttach(context: Context, preferenceStateObserver: PreferenceStateObserver)
+
+ /**
+ * Called when preference is detached from UI.
+ *
+ * Clean up and release resource.
+ */
+ fun onDetach(context: Context)
+
+ /** Observer of preference state. */
+ interface PreferenceStateObserver {
+
+ /** Callbacks when preference state is changed. */
+ fun onPreferenceStateChanged(preference: PreferenceMetadata)
+ }
+}
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceTypes.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceTypes.kt
new file mode 100644
index 0000000..ad996c7
--- /dev/null
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceTypes.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.settingslib.metadata
+
+import android.content.Context
+import androidx.annotation.StringRes
+
+/**
+ * Common base class for preferences that have two selectable states, save a boolean value, and may
+ * have dependent preferences that are enabled/disabled based on the current state.
+ */
+interface TwoStatePreference : PreferenceMetadata, PersistentPreference<Boolean>, BooleanValue {
+
+ override fun shouldDisableDependents(context: Context) =
+ storage(context).getValue(key, Boolean::class.javaObjectType) != true ||
+ super.shouldDisableDependents(context)
+}
+
+/** A preference that provides a two-state toggleable option. */
+open class SwitchPreference
+@JvmOverloads
+constructor(
+ override val key: String,
+ @StringRes override val title: Int = 0,
+ @StringRes override val summary: Int = 0,
+) : TwoStatePreference
diff --git a/packages/SettingsLib/Preference/Android.bp b/packages/SettingsLib/Preference/Android.bp
new file mode 100644
index 0000000..9665dbd
--- /dev/null
+++ b/packages/SettingsLib/Preference/Android.bp
@@ -0,0 +1,23 @@
+package {
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+filegroup {
+ name: "SettingsLibPreference-srcs",
+ srcs: ["src/**/*.kt"],
+}
+
+android_library {
+ name: "SettingsLibPreference",
+ defaults: [
+ "SettingsLintDefaults",
+ ],
+ srcs: [":SettingsLibPreference-srcs"],
+ static_libs: [
+ "SettingsLibDataStore",
+ "SettingsLibMetadata",
+ "androidx.annotation_annotation",
+ "androidx.preference_preference",
+ ],
+ kotlincflags: ["-Xjvm-default=all"],
+}
diff --git a/packages/SettingsLib/Preference/AndroidManifest.xml b/packages/SettingsLib/Preference/AndroidManifest.xml
new file mode 100644
index 0000000..2d7f7ba
--- /dev/null
+++ b/packages/SettingsLib/Preference/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.settingslib.preference">
+
+ <uses-sdk android:minSdkVersion="21" />
+</manifest>
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBinding.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBinding.kt
new file mode 100644
index 0000000..9be0e71
--- /dev/null
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBinding.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.settingslib.preference
+
+import android.content.Context
+import androidx.preference.DialogPreference
+import androidx.preference.ListPreference
+import androidx.preference.Preference
+import androidx.preference.PreferenceScreen
+import androidx.preference.SeekBarPreference
+import com.android.settingslib.metadata.DiscreteIntValue
+import com.android.settingslib.metadata.DiscreteValue
+import com.android.settingslib.metadata.PreferenceAvailabilityProvider
+import com.android.settingslib.metadata.PreferenceMetadata
+import com.android.settingslib.metadata.PreferenceScreenMetadata
+import com.android.settingslib.metadata.RangeValue
+
+/** Binding of preference widget and preference metadata. */
+interface PreferenceBinding {
+
+ /**
+ * Provides a new [Preference] widget instance.
+ *
+ * By default, it returns a new [Preference] object. Subclass could override this method to
+ * provide customized widget and do **one-off** initialization (e.g.
+ * [Preference.setOnPreferenceClickListener]). To update widget everytime when state is changed,
+ * override the [bind] method.
+ *
+ * Notes:
+ * - DO NOT set any properties defined in [PreferenceMetadata]. For example,
+ * title/summary/icon/extras/isEnabled/isVisible/isPersistent/dependency. These properties
+ * will be reset by [bind].
+ * - Override [bind] if needed to provide more information for customized widget.
+ */
+ fun createWidget(context: Context): Preference = Preference(context)
+
+ /**
+ * Binds preference widget with given metadata.
+ *
+ * Whenever metadata state is changed, this callback is invoked to update widget. By default,
+ * the common states like title, summary, enabled, etc. are already applied. Subclass should
+ * override this method to bind more data (e.g. read preference value from storage and apply it
+ * to widget).
+ *
+ * @param preference preference widget created by [createWidget]
+ * @param metadata metadata to apply
+ */
+ fun bind(preference: Preference, metadata: PreferenceMetadata) {
+ metadata.apply {
+ preference.key = key
+ if (icon != 0) {
+ preference.setIcon(icon)
+ } else {
+ preference.icon = null
+ }
+ val context = preference.context
+ preference.peekExtras()?.clear()
+ extras(context)?.let { preference.extras.putAll(it) }
+ preference.title = getPreferenceTitle(context)
+ preference.summary = getPreferenceSummary(context)
+ preference.isEnabled = isEnabled(context)
+ preference.isVisible =
+ (this as? PreferenceAvailabilityProvider)?.isAvailable(context) != false
+ preference.isPersistent = isPersistent(context)
+ metadata.order(context)?.let { preference.order = it }
+ // PreferenceRegistry will notify dependency change, so we do not need to set
+ // dependency here. This simplifies dependency management and avoid the
+ // IllegalStateException when call Preference.setDependency
+ preference.dependency = null
+ if (preference !is PreferenceScreen) { // avoid recursive loop when build graph
+ preference.fragment = (this as? PreferenceScreenCreator)?.fragmentClass()?.name
+ preference.intent = intent(context)
+ }
+ if (preference is DialogPreference) {
+ preference.dialogTitle = preference.title
+ }
+ if (preference is ListPreference && this is DiscreteValue<*>) {
+ preference.setEntries(valuesDescription)
+ if (this is DiscreteIntValue) {
+ val intValues = context.resources.getIntArray(values)
+ preference.entryValues = Array(intValues.size) { intValues[it].toString() }
+ } else {
+ preference.setEntryValues(values)
+ }
+ } else if (preference is SeekBarPreference && this is RangeValue) {
+ preference.min = minValue
+ preference.max = maxValue
+ preference.seekBarIncrement = incrementStep
+ }
+ }
+ }
+}
+
+/** Abstract preference screen to provide preference hierarchy and binding factory. */
+interface PreferenceScreenCreator : PreferenceScreenMetadata, PreferenceScreenProvider {
+
+ val preferenceBindingFactory: PreferenceBindingFactory
+ get() = DefaultPreferenceBindingFactory
+
+ override fun createPreferenceScreen(factory: PreferenceScreenFactory) =
+ factory.getOrCreatePreferenceScreen().apply {
+ inflatePreferenceHierarchy(preferenceBindingFactory, getPreferenceHierarchy(context))
+ }
+}
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindingFactory.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindingFactory.kt
new file mode 100644
index 0000000..4c2e1ba
--- /dev/null
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindingFactory.kt
@@ -0,0 +1,49 @@
+/*
+ * 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.settingslib.preference
+
+import com.android.settingslib.metadata.PreferenceGroup
+import com.android.settingslib.metadata.PreferenceMetadata
+import com.android.settingslib.metadata.SwitchPreference
+
+/** Factory to map [PreferenceMetadata] to [PreferenceBinding]. */
+interface PreferenceBindingFactory {
+
+ /** Returns the [PreferenceBinding] associated with the [PreferenceMetadata]. */
+ fun getPreferenceBinding(metadata: PreferenceMetadata): PreferenceBinding?
+}
+
+/** Default [PreferenceBindingFactory]. */
+object DefaultPreferenceBindingFactory : PreferenceBindingFactory {
+
+ override fun getPreferenceBinding(metadata: PreferenceMetadata) =
+ metadata as? PreferenceBinding
+ ?: when (metadata) {
+ is SwitchPreference -> SwitchPreferenceBinding.INSTANCE
+ is PreferenceGroup -> PreferenceGroupBinding.INSTANCE
+ is PreferenceScreenCreator -> PreferenceScreenBinding.INSTANCE
+ else -> DefaultPreferenceBinding
+ }
+}
+
+/** A preference key based binding factory. */
+class KeyedPreferenceBindingFactory(private val bindings: Map<String, PreferenceBinding>) :
+ PreferenceBindingFactory {
+
+ override fun getPreferenceBinding(metadata: PreferenceMetadata) =
+ bindings[metadata.key] ?: DefaultPreferenceBindingFactory.getPreferenceBinding(metadata)
+}
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt
new file mode 100644
index 0000000..ede970e
--- /dev/null
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt
@@ -0,0 +1,86 @@
+/*
+ * 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.settingslib.preference
+
+import android.content.Context
+import androidx.preference.Preference
+import androidx.preference.PreferenceCategory
+import androidx.preference.PreferenceScreen
+import androidx.preference.SwitchPreferenceCompat
+import com.android.settingslib.metadata.EXTRA_BINDING_SCREEN_KEY
+import com.android.settingslib.metadata.PersistentPreference
+import com.android.settingslib.metadata.PreferenceMetadata
+import com.android.settingslib.metadata.PreferenceScreenMetadata
+import com.android.settingslib.metadata.PreferenceTitleProvider
+
+/** Binding of preference group associated with [PreferenceCategory]. */
+interface PreferenceScreenBinding : PreferenceBinding {
+
+ override fun bind(preference: Preference, metadata: PreferenceMetadata) {
+ super.bind(preference, metadata)
+ val context = preference.context
+ val screenMetadata = metadata as PreferenceScreenMetadata
+ // Pass the preference key to fragment, so that the fragment could find associated
+ // preference screen registered in PreferenceScreenRegistry
+ preference.extras.putString(EXTRA_BINDING_SCREEN_KEY, preference.key)
+ if (preference is PreferenceScreen) {
+ val screenTitle = screenMetadata.screenTitle
+ preference.title =
+ if (screenTitle != 0) {
+ context.getString(screenTitle)
+ } else {
+ screenMetadata.getScreenTitle(context)
+ ?: (this as? PreferenceTitleProvider)?.getTitle(context)
+ }
+ }
+ }
+
+ companion object {
+ @JvmStatic val INSTANCE = object : PreferenceScreenBinding {}
+ }
+}
+
+/** Binding of preference group associated with [PreferenceCategory]. */
+interface PreferenceGroupBinding : PreferenceBinding {
+
+ override fun createWidget(context: Context) = PreferenceCategory(context)
+
+ companion object {
+ @JvmStatic val INSTANCE = object : PreferenceGroupBinding {}
+ }
+}
+
+/** A boolean value type preference associated with [SwitchPreferenceCompat]. */
+interface SwitchPreferenceBinding : PreferenceBinding {
+
+ override fun createWidget(context: Context): Preference = SwitchPreferenceCompat(context)
+
+ override fun bind(preference: Preference, metadata: PreferenceMetadata) {
+ super.bind(preference, metadata)
+ (metadata as? PersistentPreference<*>)
+ ?.storage(preference.context)
+ ?.getValue(metadata.key, Boolean::class.javaObjectType)
+ ?.let { (preference as SwitchPreferenceCompat).isChecked = it }
+ }
+
+ companion object {
+ @JvmStatic val INSTANCE = object : SwitchPreferenceBinding {}
+ }
+}
+
+/** Default [PreferenceBinding] for [Preference]. */
+object DefaultPreferenceBinding : PreferenceBinding
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceDataStoreAdapter.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceDataStoreAdapter.kt
new file mode 100644
index 0000000..02acfca
--- /dev/null
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceDataStoreAdapter.kt
@@ -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.settingslib.preference
+
+import androidx.preference.PreferenceDataStore
+import com.android.settingslib.datastore.KeyValueStore
+
+/** Adapter to translate [KeyValueStore] into [PreferenceDataStore]. */
+class PreferenceDataStoreAdapter(private val keyValueStore: KeyValueStore) : PreferenceDataStore() {
+
+ override fun getBoolean(key: String, defValue: Boolean): Boolean =
+ keyValueStore.getValue(key, Boolean::class.javaObjectType) ?: defValue
+
+ override fun getFloat(key: String, defValue: Float): Float =
+ keyValueStore.getValue(key, Float::class.javaObjectType) ?: defValue
+
+ override fun getInt(key: String, defValue: Int): Int =
+ keyValueStore.getValue(key, Int::class.javaObjectType) ?: defValue
+
+ override fun getLong(key: String, defValue: Long): Long =
+ keyValueStore.getValue(key, Long::class.javaObjectType) ?: defValue
+
+ override fun getString(key: String, defValue: String?): String? =
+ keyValueStore.getValue(key, String::class.javaObjectType) ?: defValue
+
+ override fun getStringSet(key: String, defValues: Set<String>?): Set<String>? =
+ (keyValueStore.getValue(key, Set::class.javaObjectType) as Set<String>?) ?: defValues
+
+ override fun putBoolean(key: String, value: Boolean) =
+ keyValueStore.setValue(key, Boolean::class.javaObjectType, value)
+
+ override fun putFloat(key: String, value: Float) =
+ keyValueStore.setValue(key, Float::class.javaObjectType, value)
+
+ override fun putInt(key: String, value: Int) =
+ keyValueStore.setValue(key, Int::class.javaObjectType, value)
+
+ override fun putLong(key: String, value: Long) =
+ keyValueStore.setValue(key, Long::class.javaObjectType, value)
+
+ override fun putString(key: String, value: String?) =
+ keyValueStore.setValue(key, String::class.javaObjectType, value)
+
+ override fun putStringSet(key: String, values: Set<String>?) =
+ keyValueStore.setValue(key, Set::class.javaObjectType, values)
+}
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceFragment.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceFragment.kt
new file mode 100644
index 0000000..2072009
--- /dev/null
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceFragment.kt
@@ -0,0 +1,109 @@
+/*
+ * 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.settingslib.preference
+
+import android.content.Context
+import android.os.Bundle
+import androidx.annotation.XmlRes
+import androidx.preference.PreferenceFragmentCompat
+import androidx.preference.PreferenceScreen
+import com.android.settingslib.metadata.EXTRA_BINDING_SCREEN_KEY
+import com.android.settingslib.metadata.PreferenceScreenBindingKeyProvider
+import com.android.settingslib.metadata.PreferenceScreenRegistry
+import com.android.settingslib.preference.PreferenceScreenBindingHelper.Companion.bindRecursively
+
+/** Fragment to display a preference screen. */
+open class PreferenceFragment :
+ PreferenceFragmentCompat(), PreferenceScreenProvider, PreferenceScreenBindingKeyProvider {
+
+ private var preferenceScreenBindingHelper: PreferenceScreenBindingHelper? = null
+
+ override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
+ preferenceScreen = createPreferenceScreen()
+ }
+
+ fun createPreferenceScreen(): PreferenceScreen? =
+ createPreferenceScreen(PreferenceScreenFactory(this))
+
+ override fun createPreferenceScreen(factory: PreferenceScreenFactory): PreferenceScreen? {
+ val context = factory.context
+ fun createPreferenceScreenFromResource() =
+ factory.inflate(getPreferenceScreenResId(context))
+
+ if (!usePreferenceScreenMetadata()) return createPreferenceScreenFromResource()
+
+ val screenKey = getPreferenceScreenBindingKey(context)
+ val screenCreator =
+ (PreferenceScreenRegistry[screenKey] as? PreferenceScreenCreator)
+ ?: return createPreferenceScreenFromResource()
+
+ val preferenceBindingFactory = screenCreator.preferenceBindingFactory
+ val preferenceHierarchy = screenCreator.getPreferenceHierarchy(context)
+ val preferenceScreen =
+ if (screenCreator.hasCompleteHierarchy()) {
+ factory.getOrCreatePreferenceScreen().apply {
+ inflatePreferenceHierarchy(preferenceBindingFactory, preferenceHierarchy)
+ }
+ } else {
+ createPreferenceScreenFromResource()?.also {
+ bindRecursively(it, preferenceBindingFactory, preferenceHierarchy)
+ } ?: return null
+ }
+ preferenceScreenBindingHelper =
+ PreferenceScreenBindingHelper(
+ context,
+ preferenceBindingFactory,
+ preferenceScreen,
+ preferenceHierarchy,
+ )
+ return preferenceScreen
+ }
+
+ /**
+ * Returns if preference screen metadata can be used to set up preference screen.
+ *
+ * This is for flagging purpose. If false (e.g. flag is disabled), xml resource is used to build
+ * preference screen.
+ */
+ protected open fun usePreferenceScreenMetadata(): Boolean = true
+
+ /** Returns the xml resource to create preference screen. */
+ @XmlRes protected open fun getPreferenceScreenResId(context: Context): Int = 0
+
+ override fun getPreferenceScreenBindingKey(context: Context): String? =
+ arguments?.getString(EXTRA_BINDING_SCREEN_KEY)
+
+ override fun onDestroy() {
+ preferenceScreenBindingHelper?.close()
+ super.onDestroy()
+ }
+
+ companion object {
+ /** Returns [PreferenceFragment] instance to display the preference screen of given key. */
+ fun of(screenKey: String): PreferenceFragment? {
+ val screenMetadata = PreferenceScreenRegistry[screenKey] ?: return null
+ if (
+ screenMetadata is PreferenceScreenCreator && screenMetadata.hasCompleteHierarchy()
+ ) {
+ return PreferenceFragment().apply {
+ arguments = Bundle().apply { putString(EXTRA_BINDING_SCREEN_KEY, screenKey) }
+ }
+ }
+ return null
+ }
+ }
+}
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceHierarchyInflater.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceHierarchyInflater.kt
new file mode 100644
index 0000000..5ef7823
--- /dev/null
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceHierarchyInflater.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.settingslib.preference
+
+import androidx.preference.PreferenceDataStore
+import androidx.preference.PreferenceGroup
+import com.android.settingslib.datastore.KeyValueStore
+import com.android.settingslib.metadata.PersistentPreference
+import com.android.settingslib.metadata.PreferenceHierarchy
+import com.android.settingslib.metadata.PreferenceMetadata
+
+/** Inflates [PreferenceHierarchy] into given [PreferenceGroup] recursively. */
+fun PreferenceGroup.inflatePreferenceHierarchy(
+ preferenceBindingFactory: PreferenceBindingFactory,
+ hierarchy: PreferenceHierarchy,
+ storages: MutableMap<KeyValueStore, PreferenceDataStore> = mutableMapOf(),
+) {
+ fun PreferenceMetadata.preferenceBinding() = preferenceBindingFactory.getPreferenceBinding(this)
+
+ hierarchy.metadata.let { it.preferenceBinding()?.bind(this, it) }
+ hierarchy.forEach {
+ val metadata = it.metadata
+ val preferenceBinding = metadata.preferenceBinding() ?: return@forEach
+ val widget = preferenceBinding.createWidget(context)
+ if (it is PreferenceHierarchy) {
+ val preferenceGroup = widget as PreferenceGroup
+ // MUST add preference before binding, otherwise exception is raised when add child
+ addPreference(preferenceGroup)
+ preferenceGroup.inflatePreferenceHierarchy(preferenceBindingFactory, it)
+ } else {
+ preferenceBinding.bind(widget, metadata)
+ (metadata as? PersistentPreference<*>)?.storage(context)?.let { storage ->
+ widget.preferenceDataStore =
+ storages.getOrPut(storage) { PreferenceDataStoreAdapter(storage) }
+ }
+ // MUST add preference after binding for persistent preference to get initial value
+ // (preference key is set within bind method)
+ addPreference(widget)
+ }
+ }
+}
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt
new file mode 100644
index 0000000..3610894
--- /dev/null
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt
@@ -0,0 +1,200 @@
+/*
+ * 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.settingslib.preference
+
+import android.content.Context
+import android.os.Handler
+import android.os.Looper
+import androidx.preference.Preference
+import androidx.preference.PreferenceGroup
+import androidx.preference.PreferenceScreen
+import com.android.settingslib.datastore.KeyedDataObservable
+import com.android.settingslib.datastore.KeyedObservable
+import com.android.settingslib.datastore.KeyedObserver
+import com.android.settingslib.metadata.PersistentPreference
+import com.android.settingslib.metadata.PreferenceHierarchy
+import com.android.settingslib.metadata.PreferenceLifecycleProvider
+import com.android.settingslib.metadata.PreferenceMetadata
+import com.android.settingslib.metadata.PreferenceScreenRegistry
+import com.google.common.collect.ImmutableMap
+import com.google.common.collect.ImmutableMultimap
+import java.util.concurrent.Executor
+
+/**
+ * Helper to bind preferences on given [preferenceScreen].
+ *
+ * When there is any preference change event detected (e.g. preference value changed, runtime
+ * states, dependency is updated), this helper class will re-bind [PreferenceMetadata] to update
+ * widget UI.
+ */
+class PreferenceScreenBindingHelper(
+ context: Context,
+ private val preferenceBindingFactory: PreferenceBindingFactory,
+ private val preferenceScreen: PreferenceScreen,
+ preferenceHierarchy: PreferenceHierarchy,
+) : KeyedDataObservable<String>(), AutoCloseable {
+
+ private val handler = Handler(Looper.getMainLooper())
+ private val executor =
+ object : Executor {
+ override fun execute(command: Runnable) {
+ handler.post(command)
+ }
+ }
+
+ private val preferences: ImmutableMap<String, PreferenceMetadata>
+ private val dependencies: ImmutableMultimap<String, String>
+ private val storages = mutableSetOf<KeyedObservable<String>>()
+
+ private val preferenceObserver: KeyedObserver<String?>
+
+ private val storageObserver =
+ KeyedObserver<String?> { key, _ ->
+ if (key != null) {
+ notifyChange(key, CHANGE_REASON_VALUE)
+ }
+ }
+
+ private val stateObserver =
+ object : PreferenceLifecycleProvider.PreferenceStateObserver {
+ override fun onPreferenceStateChanged(preference: PreferenceMetadata) {
+ notifyChange(preference.key, CHANGE_REASON_STATE)
+ }
+ }
+
+ init {
+ val preferencesBuilder = ImmutableMap.builder<String, PreferenceMetadata>()
+ val dependenciesBuilder = ImmutableMultimap.builder<String, String>()
+ fun PreferenceMetadata.addDependency(dependency: PreferenceMetadata) {
+ dependenciesBuilder.put(key, dependency.key)
+ }
+
+ fun PreferenceMetadata.add() {
+ preferencesBuilder.put(key, this)
+ dependencyOfEnabledState(context)?.addDependency(this)
+ if (this is PreferenceLifecycleProvider) onAttach(context, stateObserver)
+ if (this is PersistentPreference<*>) storages.add(storage(context))
+ }
+
+ fun PreferenceHierarchy.addPreferences() {
+ metadata.add()
+ forEach {
+ if (it is PreferenceHierarchy) {
+ it.addPreferences()
+ } else {
+ it.metadata.add()
+ }
+ }
+ }
+
+ preferenceHierarchy.addPreferences()
+ this.preferences = preferencesBuilder.buildOrThrow()
+ this.dependencies = dependenciesBuilder.build()
+
+ preferenceObserver = KeyedObserver { key, reason -> onPreferenceChange(key, reason) }
+ addObserver(preferenceObserver, executor)
+ for (storage in storages) storage.addObserver(storageObserver, executor)
+ }
+
+ private fun onPreferenceChange(key: String?, reason: Int) {
+ if (key == null) return
+
+ // bind preference to update UI
+ preferenceScreen.findPreference<Preference>(key)?.let {
+ preferenceBindingFactory.bind(it, preferences[key])
+ }
+
+ // check reason to avoid potential infinite loop
+ if (reason != CHANGE_REASON_DEPENDENT) {
+ notifyDependents(key, mutableSetOf())
+ }
+ }
+
+ /** Notifies dependents recursively. */
+ private fun notifyDependents(key: String, notifiedKeys: MutableSet<String>) {
+ if (!notifiedKeys.add(key)) return
+ for (dependency in dependencies[key]) {
+ notifyChange(dependency, CHANGE_REASON_DEPENDENT)
+ notifyDependents(dependency, notifiedKeys)
+ }
+ }
+
+ override fun close() {
+ removeObserver(preferenceObserver)
+ val context = preferenceScreen.context
+ for (preference in preferences.values) {
+ if (preference is PreferenceLifecycleProvider) preference.onDetach(context)
+ }
+ for (storage in storages) storage.removeObserver(storageObserver)
+ }
+
+ companion object {
+ /** Preference value is changed. */
+ private const val CHANGE_REASON_VALUE = 0
+ /** Preference state (title/summary, enable state, etc.) is changed. */
+ private const val CHANGE_REASON_STATE = 1
+ /** Dependent preference state is changed. */
+ private const val CHANGE_REASON_DEPENDENT = 2
+
+ /** Updates preference screen that has incomplete hierarchy. */
+ @JvmStatic
+ fun bind(preferenceScreen: PreferenceScreen) {
+ PreferenceScreenRegistry[preferenceScreen.key]?.run {
+ if (!hasCompleteHierarchy()) {
+ val preferenceBindingFactory =
+ (this as? PreferenceScreenCreator)?.preferenceBindingFactory ?: return
+ bindRecursively(
+ preferenceScreen,
+ preferenceBindingFactory,
+ getPreferenceHierarchy(preferenceScreen.context),
+ )
+ }
+ }
+ }
+
+ internal fun bindRecursively(
+ preferenceScreen: PreferenceScreen,
+ preferenceBindingFactory: PreferenceBindingFactory,
+ preferenceHierarchy: PreferenceHierarchy,
+ ) =
+ preferenceScreen.bindRecursively(
+ preferenceBindingFactory,
+ preferenceHierarchy.getAllPreferences().associateBy { it.key },
+ )
+
+ private fun PreferenceGroup.bindRecursively(
+ preferenceBindingFactory: PreferenceBindingFactory,
+ preferences: Map<String, PreferenceMetadata>,
+ ) {
+ preferenceBindingFactory.bind(this, preferences[key])
+ val count = preferenceCount
+ for (index in 0 until count) {
+ val preference = getPreference(index)
+ if (preference is PreferenceGroup) {
+ preference.bindRecursively(preferenceBindingFactory, preferences)
+ } else {
+ preferenceBindingFactory.bind(preference, preferences[preference.key])
+ }
+ }
+ }
+
+ private fun PreferenceBindingFactory.bind(
+ preference: Preference,
+ metadata: PreferenceMetadata?,
+ ) = metadata?.let { getPreferenceBinding(it)?.bind(preference, it) }
+ }
+}
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenFactory.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenFactory.kt
new file mode 100644
index 0000000..7f99d7a
--- /dev/null
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenFactory.kt
@@ -0,0 +1,106 @@
+/*
+ * 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.settingslib.preference
+
+import android.content.Context
+import androidx.preference.Preference
+import androidx.preference.PreferenceFragmentCompat
+import androidx.preference.PreferenceManager
+import androidx.preference.PreferenceScreen
+import com.android.settingslib.metadata.PreferenceScreenRegistry
+
+/** Factory to create preference screen. */
+class PreferenceScreenFactory {
+ /** Preference manager to create/inflate preference screen. */
+ val preferenceManager: PreferenceManager
+
+ /**
+ * Optional existing hierarchy to merge the new hierarchies into.
+ *
+ * Provide existing hierarchy will preserve the internal state (e.g. scrollbar position) for
+ * [PreferenceFragmentCompat].
+ */
+ private val rootScreen: PreferenceScreen?
+
+ /**
+ * Factory constructor from preference fragment.
+ *
+ * The fragment must be within a valid lifecycle.
+ */
+ constructor(preferenceFragment: PreferenceFragmentCompat) {
+ preferenceManager = preferenceFragment.preferenceManager
+ rootScreen = preferenceFragment.preferenceScreen
+ }
+
+ /** Factory constructor from [Context]. */
+ constructor(context: Context) : this(PreferenceManager(context))
+
+ /** Factory constructor from [PreferenceManager]. */
+ constructor(preferenceManager: PreferenceManager) {
+ this.preferenceManager = preferenceManager
+ rootScreen = null
+ }
+
+ /** Context of the factory to create preference screen. */
+ val context: Context
+ get() = preferenceManager.context
+
+ /** Returns the existing hierarchy or create a new empty preference screen. */
+ fun getOrCreatePreferenceScreen(): PreferenceScreen =
+ rootScreen ?: preferenceManager.createPreferenceScreen(context)
+
+ /**
+ * Inflates [PreferenceScreen] from xml resource.
+ *
+ * @param xmlRes The resource ID of the XML to inflate
+ * @return The root hierarchy (if one was not provided, the new hierarchy's root)
+ */
+ fun inflate(xmlRes: Int): PreferenceScreen? =
+ if (xmlRes != 0) {
+ preferenceManager.inflateFromResource(preferenceManager.context, xmlRes, rootScreen)
+ } else {
+ rootScreen
+ }
+
+ /**
+ * Creates [PreferenceScreen] of given key.
+ *
+ * The screen must be registered in [PreferenceScreenFactory] and provide a complete hierarchy.
+ */
+ fun createBindingScreen(screenKey: String?): PreferenceScreen? {
+ val metadata = PreferenceScreenRegistry[screenKey] ?: return null
+ if (metadata is PreferenceScreenCreator && metadata.hasCompleteHierarchy()) {
+ return metadata.createPreferenceScreen(this)
+ }
+ return null
+ }
+
+ companion object {
+ /** Creates [PreferenceScreen] from [PreferenceScreenRegistry]. */
+ @JvmStatic
+ fun createBindingScreen(preference: Preference): PreferenceScreen? {
+ val preferenceScreenCreator =
+ (PreferenceScreenRegistry[preference.key] as? PreferenceScreenCreator)
+ ?: return null
+ if (!preferenceScreenCreator.hasCompleteHierarchy()) return null
+ val factory = PreferenceScreenFactory(preference.context)
+ val preferenceScreen = preferenceScreenCreator.createPreferenceScreen(factory)
+ factory.preferenceManager.setPreferences(preferenceScreen)
+ return preferenceScreen
+ }
+ }
+}
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenProvider.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenProvider.kt
new file mode 100644
index 0000000..0573292
--- /dev/null
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenProvider.kt
@@ -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.
+ */
+
+package com.android.settingslib.preference
+
+import android.content.Context
+import androidx.preference.PreferenceScreen
+
+/**
+ * Interface to provide [PreferenceScreen].
+ *
+ * When implemented by Activity/Fragment, the Activity/Fragment [Context] APIs (e.g. `getContext()`,
+ * `getActivity()`) MUST not be used: preference screen creation could happen in background service,
+ * where the Activity/Fragment lifecycle callbacks (`onCreate`, `onDestroy`, etc.) are not invoked
+ * and context APIs return null.
+ */
+interface PreferenceScreenProvider {
+
+ /**
+ * Creates [PreferenceScreen].
+ *
+ * Preference screen creation could happen in background service. The implementation MUST use
+ * [PreferenceScreenFactory.context] to obtain context.
+ */
+ fun createPreferenceScreen(factory: PreferenceScreenFactory): PreferenceScreen?
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt
index 90cee16..1f3e2425 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt
@@ -25,6 +25,13 @@
val paddingLarge = 16.dp
val paddingExtraLarge = 24.dp
+ val spinnerHorizontalPadding = paddingExtraLarge
+ val spinnerVerticalPadding = paddingLarge
+
+ val actionIconWidth = 32.dp
+ val actionIconHeight = 40.dp
+ val actionIconPadding = 4.dp
+
val itemIconSize = 24.dp
val itemIconContainerSize = 72.dp
val itemPaddingStart = paddingExtraLarge
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTheme.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTheme.kt
index d9f82e8..15def72 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTheme.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTheme.kt
@@ -40,3 +40,5 @@
}
}
}
+
+const val isSpaExpressiveEnabled = false
\ No newline at end of file
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt
index 5f320f7..9bbc16d 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt
@@ -17,15 +17,24 @@
package com.android.settingslib.spa.widget.scaffold
import androidx.appcompat.R
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
import androidx.compose.material.icons.outlined.Clear
import androidx.compose.material.icons.outlined.FindInPage
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource
import com.android.settingslib.spa.framework.compose.LocalNavController
+import com.android.settingslib.spa.framework.theme.SettingsDimension
+import com.android.settingslib.spa.framework.theme.SettingsShape
+import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled
/** Action that navigates back to last page. */
@Composable
@@ -50,6 +59,11 @@
Icon(
imageVector = Icons.AutoMirrored.Outlined.ArrowBack,
contentDescription = contentDescription,
+ modifier = if (isSpaExpressiveEnabled) Modifier
+ .size(SettingsDimension.actionIconWidth, SettingsDimension.actionIconHeight)
+ .clip(SettingsShape.CornerExtraLarge)
+ .background(MaterialTheme.colorScheme.onSurfaceVariant)
+ .padding(SettingsDimension.actionIconPadding) else Modifier
)
}
}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsScaffold.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsScaffold.kt
index 4cf741e..7d8ee79 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsScaffold.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsScaffold.kt
@@ -39,6 +39,7 @@
import com.android.settingslib.spa.framework.compose.horizontalValues
import com.android.settingslib.spa.framework.compose.verticalValues
import com.android.settingslib.spa.framework.theme.SettingsTheme
+import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled
import com.android.settingslib.spa.framework.theme.settingsBackground
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
@@ -55,6 +56,10 @@
) {
ActivityTitle(title)
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
+ if (isSpaExpressiveEnabled) {
+ LaunchedEffect(scrollBehavior.state.heightOffsetLimit) { scrollBehavior.collapse() }
+ }
+
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = { SettingsTopAppBar(title, scrollBehavior, actions) },
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Spinner.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Spinner.kt
index c48a147..6b2db90 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Spinner.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Spinner.kt
@@ -46,6 +46,7 @@
import androidx.compose.ui.unit.dp
import com.android.settingslib.spa.framework.theme.SettingsDimension
import com.android.settingslib.spa.framework.theme.SettingsTheme
+import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled
data class SpinnerOption(
val id: Int,
@@ -70,7 +71,10 @@
)
.selectableGroup(),
) {
- val contentPadding = PaddingValues(horizontal = SettingsDimension.itemPaddingEnd)
+ val contentPadding = if (isSpaExpressiveEnabled) PaddingValues(
+ horizontal = SettingsDimension.spinnerHorizontalPadding,
+ vertical = SettingsDimension.spinnerVerticalPadding
+ ) else PaddingValues(horizontal = SettingsDimension.itemPaddingEnd)
Button(
modifier = Modifier.semantics { role = Role.DropdownList },
onClick = { expanded = true },
@@ -129,7 +133,11 @@
text = option?.text ?: "",
modifier = modifier
.padding(end = SettingsDimension.itemPaddingEnd)
- .padding(vertical = SettingsDimension.itemPaddingAround),
+ .then(
+ if (!isSpaExpressiveEnabled)
+ Modifier.padding(vertical = SettingsDimension.itemPaddingAround)
+ else Modifier
+ ),
color = color,
style = MaterialTheme.typography.labelLarge,
)
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt
index 2fac576..8619f31 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Switch.kt
@@ -17,11 +17,18 @@
package com.android.settingslib.spa.widget.ui
import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.size
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Check
+import androidx.compose.material.icons.filled.Close
+import androidx.compose.material3.Icon
import androidx.compose.material3.Switch
+import androidx.compose.material3.SwitchDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import com.android.settingslib.spa.framework.compose.contentDescription
+import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled
import com.android.settingslib.spa.framework.util.wrapOnSwitchWithLog
@Composable
@@ -39,13 +46,42 @@
modifier = Modifier.contentDescription(contentDescription),
enabled = changeable(),
interactionSource = interactionSource,
- )
+ thumbContent =
+ if (isSpaExpressiveEnabled) {
+ if (checked) {
+ {
+ Icon(
+ imageVector = Icons.Filled.Check,
+ contentDescription = null,
+ modifier = Modifier.size(SwitchDefaults.IconSize),
+ )
+ }
+ } else {
+ {
+ Icon(
+ imageVector = Icons.Filled.Close,
+ contentDescription = null,
+ modifier = Modifier.size(SwitchDefaults.IconSize),
+ )
+ }
+ }
+ } else null)
} else {
Switch(
checked = false,
onCheckedChange = null,
enabled = false,
interactionSource = interactionSource,
+ thumbContent =
+ if (isSpaExpressiveEnabled) {
+ {
+ Icon(
+ imageVector = Icons.Filled.Close,
+ contentDescription = null,
+ modifier = Modifier.size(SwitchDefaults.IconSize),
+ )
+ }
+ } else null
)
}
}
diff --git a/packages/SettingsLib/aconfig/settingslib.aconfig b/packages/SettingsLib/aconfig/settingslib.aconfig
index 2b3862f..34b597b 100644
--- a/packages/SettingsLib/aconfig/settingslib.aconfig
+++ b/packages/SettingsLib/aconfig/settingslib.aconfig
@@ -129,3 +129,13 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "member_device_lea_active_state_sync_fix"
+ namespace: "cross_device_experiences"
+ description: "Gates whether to enable fix for member device active state sync on lea profile"
+ bug: "364201289"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 1161a30..9c75556 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wekkers en onthounotas"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Laat hierdie app toe om wekkers te stel en tydsensitiewe handelinge te skeduleer. Dit laat die app op die agtergrond werk, wat meer batterykrag kan gebruik.\n\nAs hierdie toestemming af is, sal bestaande wekkers en tydgegronde geleenthede wat deur hierdie app geskeduleer is, nie werk nie."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"skedule, wekker, onthounota, horlosie"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Moenie Steur Nie"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Skakel aan"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Skakel Moenie steur nie aan"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 8aae837..093fbbb 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"ማንቂያዎች እና አስታዋሾች"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ይህ መተግበሪያ ማንቂያዎችን እንዲያቀናብር እና የጊዜ ትብነት ያላቸው እርምጃዎችን መርሐግብር እንዲያስይዝ ይፍቀዱለት። ይህ መተግበሪያው ከበስተጀርባ ማሄድ እንዲችል ያስችለዋል፣ ይህም የበለጠ ባትሪ ሊጠቀም ይችላል።\n\nይህ ፈቃድ ከጠፋ በዚህ መተግበሪያ መርሐግብር የተያዘላቸው ነባር ማንቂያዎች እና ጊዜ-ተኮር ክስተቶች አይሰሩም።"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"የጊዜ መርሐግብር፣ ማንቂያ፣ አስታዋሽ ሰዓት"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"አይረብሹ"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"አብራ"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"አትረብሽን አብራ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 02fa9aa..a1f4109 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"المنبّهات والتذكيرات"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"يمكنك السماح لهذا التطبيق بضبط المنبّهات وجدولة الإجراءات لتنفيذها في الوقت المناسب. ويسمح هذا الإذن بتشغيل التطبيق في الخلفية، ما قد يستهلك المزيد من البطارية.\n\nفي حال عدم تفعيل هذا الإذن، لن تعمل المنبهات المضبوطة والأحداث المستندة إلى الوقت المجدولة حاليًا في هذا التطبيق."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"جدول زمني، جدولة، منبّه، تذكير، ساعة"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"وضع \"عدم الإزعاج\""</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"تفعيل"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"تفعيل ميزة \"عدم الإزعاج\""</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index f7c68a3..019fb86 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"এলাৰ্ম আৰু ৰিমাইণ্ডাৰ"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"এই এপ্টোক এলাৰ্ম ছেট কৰিবলৈ আৰু সময় সংবেদনশীল কাৰ্যৰ সময়সূচী নিৰ্ধাৰণ কৰিবলৈ দিয়ক। ই এপ্টোক নেপথ্যত চলি থকাৰ অনুমতি দিয়ে যাৰ ফলত অধিক বেটাৰী ব্যৱহাৰ হয়।\n\nএই অনুমতিটো অফ কৰা থাকিলে, ইতিমধ্যে ছেট কৰা এলাৰ্ম আৰু এই এপ্টোৱে সময়সূচী নিৰ্ধাৰণ কৰা সময় ভিত্তিক অনুষ্ঠানসমূহে কাম নকৰা হ’ব।"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"সময়সূচী, এলাৰ্ম, ৰিমাইণ্ডাৰ, ঘড়ী"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"অসুবিধা নিদিব"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"অন কৰক"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"অসুবিধা নিদিব অন কৰক"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 4a08007..7f17e79 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Siqnallar və xatırlatmalar"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Bu tətbiqə siqnallar ayarlamağa və vaxta əsaslanan əməliyyatları planlaşdırmağa icazə verin. Bu, tətbiqin arxa fonda işləməsinə imkan verir ki, nəticədə daha çox enerji istifadə edilə bilər.\n\nBu icazə deaktiv olsa, bu tətbiq tərəfindən planlaşdırılan mövcud siqnallar və vaxta əsaslanan tədbirlər işləməyəcəkdir."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"cədvəl, siqnal, xatırlatma, saat"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Narahat etməyin"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktiv edin"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\"Narahat Etməyin\" rejimini aktiv edin"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 617533f..25bf587 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi i podsetnici"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Omogućite ovoj aplikaciji da podešava alarme i zakazuje vremenski osetljive radnje. To omogućava da aplikacija bude pokrenuta u pozadini, što može da troši više baterije.\n\nAko je ova dozvola isključena, postojeći alarmi i događaji zasnovani na vremenu zakazani pomoću ove aplikacije neće raditi."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"zakazati, alarm, podsetnik, sat"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Ne uznemiravaj"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Uključi"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Uključite režim Ne uznemiravaj"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index f5c4440..3a61980 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Будзільнікі і напаміны"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Дазвольце гэтай праграме ўключаць будзільнікі і задаваць час дзеянняў. З такім дазволам праграма можа працаваць у фонавым рэжыме і ў выніку хутчэй разраджаць акумулятар.\n\nКалі вы не ўключыце гэты дазвол, існуючыя будзільнікі і запланаваны праграмай час падзей не будуць працаваць."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"расклад, будзільнік, напамін, гадзіннік"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Не турбаваць"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Уключыць"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Уключэнне рэжыму \"Не турбаваць\""</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index ecf1e5a..5f0def5 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Будилници и напомняния"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Разрешаване на това приложение да задава будилници и да насрочва действия, ограничени във времето. Това му позволява да работи на заден план, при което може да се използва повече батерия.\n\nАко разрешението е изключено, съществуващите будилници и събитията въз основа на времето, насрочени от приложението, няма да работят."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"график, будилник, напомняне, часовник"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Не безпокойте"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Включване"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Включване на режима „Не безпокойте“"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index b6fde48..0c0b569 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"অ্যালার্ম এবং রিমাইন্ডার"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"অ্যালার্ম এবং সময়ের মধ্যে শেষ করতে হবে এমন অ্যাকশনের শিডিউল সেট করতে এই অ্যাপকে অনুমতি দিন। এর ফলে ব্যাকগ্রাউন্ডে অ্যাপ চলতে পারে, যার জন্য আরও ব্যাটারির চার্জ খরচ হতে পারে।\n\nএই অনুমতি বন্ধ করা থাকলে, আগে থেকে থাকা অ্যালার্ম এবং অ্যাপের মাধ্যমে শিডিউল করা সময় ভিত্তিক ইভেন্টের রিমাইন্ডার কাজ করবে না।"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"শিডিউল, অ্যালার্ম, রিমাইন্ডার, ঘড়ি"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"বিরক্ত করবে না"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"চালু করুন"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\'বিরক্ত করবে না\' মোড চালু করুন"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 44391d5..ea4150f 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi i podsjetnici"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Dozvolite ovoj aplikaciji da postavlja alarme i zakazuje vremenski osjetljive radnje. Ovim će se omogućiti aplikaciji da radi u pozadini, čime se može povećati potrošnja baterije.\n\nAko je ovo odobrenje isključeno, postojeći alarmi i događaji zasnovani na vremenu, a koje je ova aplikacija zakazala, neće funkcionirati."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"raspored, alarm, podsjetnik, sat"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Ne ometaj"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Uključi"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Uključi način rada Ne ometaj"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 9079c73..adfa6f2 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes i recordatoris"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permet que aquesta aplicació configuri alarmes i programi accions a una hora determinada. Això permet a l\'aplicació executar-se en segon pla i, per tant, és possible que consumeixi més bateria.\n\nSi aquest permís està desactivat, les alarmes i els esdeveniments que ja hagi programat l\'aplicació no funcionaran."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programació, alarma, recordatori, rellotge"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"No molestis"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activa"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activa el mode No molestis"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 33955de..96d04a8 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Budíky a připomenutí"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Když tuto možnost povolíte, aplikace bude moci nastavovat budíky a plánovat akce závislé na čase. Aplikace poběží na pozadí, což může vést k vyšší spotřebě baterie.\n\nPokud toto oprávnění zůstane vypnuté, stávající budíky a události závislé na čase naplánované touto aplikací nebudou fungovat."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"plán, budík, připomenutí, hodiny"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Nerušit"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Zapnout"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Zapněte funkci Nerušit"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index de09e95..c6a5a43 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmer og påmindelser"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Tillad, at denne app indstiller alarmer og planlægger tidsbestemte handlinger. Appen vil køre i baggrunden, hvor den muligvis bruger mere batteri.\n\nHvis denne tilladelse er deaktiveret, vil eksisterende alarmer og tidsbestemte handlinger, der er planlagt af denne app, ikke fungere."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"planlæg, alarm, påmindelse, ur"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Forstyr ikke"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktivér"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktivér Forstyr ikke"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index f24fb35..88db823 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wecker und Erinnerungen"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Dieser App erlauben, Wecker zu stellen und zeitgebundene Aktionen zu planen. Dadurch läuft die App im Hintergrund. Dies kann den Akkuverbrauch erhöhen. \n\nWenn diese Berechtigung deaktiviert ist, funktionieren bereits gestellte Wecker und zeitgebundene Ereignisse, die von dieser App geplant sind, nicht wie erwartet."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"planen, Wecker, Erinnerung, Uhr"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Bitte nicht stören"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktivieren"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"„Bitte nicht stören“ aktivieren"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index bb518d7..35734a9 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Ξυπνητήρια και υπενθυμίσεις"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Επιτρέψτε σε αυτή την εφαρμογή να ορίζει ξυπνητήρια και να προγραμματίζει ενέργειες που εξαρτώνται από τον χρόνο. Αυτό επιτρέπει στην εφαρμογή να εκτελείται στο παρασκήνιο και, ως εκ τούτου, μπορεί να καταναλώνει περισσότερη μπαταρία.\n\nΑν αυτή η άδεια δεν είναι ενεργή, τα υπάρχοντα ξυπνητήρια και συμβάντα βάσει χρόνου που έχουν προγραμματιστεί από αυτή την εφαρμογή δεν θα λειτουργούν."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"πρόγραμμα, ξυπνητήρι, υπενθύμιση, ρολόι"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Μην ενοχλείτε"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ενεργοποίηση"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ενεργοποίηση λειτουργίας \"Μην ενοχλείτε\""</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 73502ed..2d03437 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms and reminders"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Allow this app to set alarms and schedule time-sensitive actions. This lets the app run in the background, which may use more battery.\n\nIf this permission is off, existing alarms and time-based events scheduled by this app won’t work."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"schedule, alarm, reminder, clock"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Do Not Disturb"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Turn on"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Turn on Do Not Disturb"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index c0b0dff..be5dfaa 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -564,6 +564,7 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms & reminders"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Allow this app to set alarms and schedule time-sensitive actions. This lets the app run in the background, which may use more battery.\n\nIf this permission is off, existing alarms and time-based events scheduled by this app won’t work."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"schedule, alarm, reminder, clock"</string>
+ <string name="zen_mode_do_not_disturb_name" msgid="6798711401734798283">"Do Not Disturb"</string>
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Do Not Disturb"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Turn on"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Turn on Do Not Disturb"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 73502ed..2d03437 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms and reminders"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Allow this app to set alarms and schedule time-sensitive actions. This lets the app run in the background, which may use more battery.\n\nIf this permission is off, existing alarms and time-based events scheduled by this app won’t work."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"schedule, alarm, reminder, clock"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Do Not Disturb"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Turn on"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Turn on Do Not Disturb"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 73502ed..2d03437 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms and reminders"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Allow this app to set alarms and schedule time-sensitive actions. This lets the app run in the background, which may use more battery.\n\nIf this permission is off, existing alarms and time-based events scheduled by this app won’t work."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"schedule, alarm, reminder, clock"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Do Not Disturb"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Turn on"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Turn on Do Not Disturb"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 59be4be..92af284 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -564,6 +564,7 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarms & reminders"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Allow this app to set alarms and schedule time-sensitive actions. This lets the app run in the background, which may use more battery.\n\nIf this permission is off, existing alarms and time-based events scheduled by this app won’t work."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"schedule, alarm, reminder, clock"</string>
+ <string name="zen_mode_do_not_disturb_name" msgid="6798711401734798283">"Do Not Disturb"</string>
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Do Not Disturb"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Turn on"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Turn on Do Not Disturb"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 2cfd356..ff69f64 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmas y recordatorios"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite que esta app establezca alarmas y programe acciones para horarios específicos. De esta manera, la app puede ejecutarse en segundo plano, lo que podría aumentar el consumo de batería.\n\nSi se desactiva este permiso, no funcionarán las alarmas ni los eventos basados en el tiempo existentes que programe esta app."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarma, recordatorio, reloj"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"No interrumpir"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activar"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activar No interrumpir"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 6779f46..e2d3589 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmas y recordatorios"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite que esta aplicación programe alarmas y otras acciones que se llevan a cabo a una hora determinada. Esto hace que la aplicación pueda seguir activa en segundo plano, lo que puede usar más batería.\n\nSi este permiso está desactivado, no funcionarán las alarmas ni los eventos que se activan a una hora determinada que programe esta aplicación."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarma, recordatorio, reloj"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"No molestar"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activar"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activar el modo No molestar"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 4cb05ba..e4490a3 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmid ja meeldetuletused"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Lubage sellel rakendusel määrata alarme ja ajastada ajakriitilisi toiminguid. See võimaldab rakendusel töötada taustal, mistõttu võib akukasutus olla suurem.\n\nKui see luba on välja lülitatud, siis olemasolevad alarmid ja selle rakenduse ajastatud ajapõhised sündmused ei tööta."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ajakava, äratus, meeldetuletus, kell"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Mitte segada"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Lülita sisse"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Valiku Mitte segada sisselülitamine"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 666af7c..828831e 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmak eta abisuak"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Eman alarmak ezartzeko eta denbora-muga duten ekintzak programatzeko baimena aplikazioari. Hala, aplikazioak atzeko planoan funtzionatuko du, eta litekeena da bateria gehiago kontsumitzea.\n\nBaimen hori ematen ez baduzu, ez dute funtzionatuko aplikazio honen bidez programatutako alarmek eta denbora-muga duten ekintzek."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programazioa, alarma, abisua, erlojua"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Ez molestatzeko modua"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktibatu"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktibatu ez molestatzeko modua"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index f2a2bb5..7858cc8 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"زنگهای ساعت و یادآوریها"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"به این برنامه اجازه میدهد زنگ ساعت تنظیم کند و کنشهای حساس به زمان را زمانبندی کند. این تنظیم به برنامه اجازه میدهد در پسزمینه اجرا شود که ممکن است باتری بیشتری مصرف کند.\n\nاگر این اجازه خاموش باشد، زنگهای ساعت موجود و رویدادهای زمانمحور که این برنامه زمانبندی کرده است کار نخواهند کرد."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"زمانبندی، زنگ ساعت، یادآوری، ساعت"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"مزاحم نشوید"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"روشن کردن"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"روشن کردن «مزاحم نشوید»"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 66db8f7..8ad343a 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Herätykset ja muistutukset"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Anna sovelluksen lisätä herätyksiä ja ajoittaa kiireellisiä tapahtumia. Näin sovellus voi toimia taustalla, mikä voi kuluttaa enemmän virtaa.\n\nIlman tätä lupaa sovelluksen ajoittamat herätykset ja aikaan perustuvat tapahtumat eivät toimi."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ajoitus, herätys, muistutus, kello"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Älä häiritse"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ota käyttöön"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Laita Älä häiritse ‑tila päälle"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 6ce0e82..2e3a6a7 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes et rappels"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Autorisez cette appli à créer des alarmes et à programmer des actions urgentes. Cela permet à l’appli de s\'exécuter en arrière-plan, ce qui peut nécessiter plus de pile.\n\nSi cette autorisation est désactivée, les alarmes existantes et les événements en temps réel programmés par cette appli ne fonctionneront pas."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"horaire, alarme, rappel, horloge"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Ne pas déranger"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activer"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activer le mode Ne pas déranger"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index ea24b23..4327708 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes et rappels"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Autoriser cette appli à définir des alarmes et à programmer des actions à certaines heures. Elle s\'exécutera alors en arrière-plan, ce qui peut solliciter davantage la batterie.\n\nSi l\'autorisation est désactivée, les alarmes existantes et les événements programmés par l\'appli ne fonctionneront pas."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"définir, alarme, rappel, horloge"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Ne pas déranger"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activer"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activer le mode Ne pas déranger"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 647f6dd..9bcdc97 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmas e recordatorios"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite que esta aplicación defina alarmas e planifique accións que dependan da hora. Con este permiso, a aplicación pode executarse en segundo plano, o que pode provocar un maior consumo de batería.\n\nSe este permiso está desactivado, non funcionarán as alarmas que xa se definisen nin os eventos que dependan da hora planificados por esta aplicación."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"planificar, alarma, recordatorio, reloxo"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Non molestar"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activar"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activar modo Non molestar"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index f739410..e402ad3 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -130,7 +130,7 @@
<string name="bluetooth_profile_pbap" msgid="2103406516858653017">"સંપર્કો અને કૉલ ઇતિહાસ ઍક્સેસ કરવા દો"</string>
<string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"માહિતીનો ઉપયોગ કૉલની ઘોષણાઓ અને વધુ બાબતો માટે કરવામાં આવશે"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ઇન્ટરનેટ કનેક્શન શેરિંગ"</string>
- <string name="bluetooth_profile_map" msgid="8907204701162107271">"ટેક્સ્ટ સંદેશા"</string>
+ <string name="bluetooth_profile_map" msgid="8907204701162107271">"ટેક્સ્ટ મેસેજ"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"સિમ ઍક્સેસ"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD ઑડિયો: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD ઑડિયો"</string>
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"અલાર્મ અને રિમાઇન્ડર"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"આ ઍપને અલાર્મ સેટ કરવા અને સમય પ્રતિ સંવેદનશીલ ક્રિયાઓ શેડ્યૂલ કરવા માટે મંજૂરી આપો. આ ઍપને બૅકગ્રાઉન્ડમાં ચાલવા દે છે, જેને કારણે બૅટરીનો વધુ વપરાશ થઈ શકે છે.\n\nજો આ પરવાનગી બંધ હોય, તો આ ઍપ દ્વારા શેડ્યૂલ કરવામાં આવેલા વર્તમાન અલાર્મ અને સમય આધારિત ઇવેન્ટ કામ કરશે નહીં."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"શેડ્યૂલ, અલાર્મ, રિમાઇન્ડર, ઘડિયાળ"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"ખલેલ પાડશો નહીં"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ચાલુ કરો"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"ખલેલ પાડશો નહીં ચાલુ કરો"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index cdab138..2e484e4 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"अलार्म और रिमाइंडर"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"इस ऐप्लिकेशन को अलार्म और तय समय पर होने वाली कार्रवाइयों के रिमाइंडर सेट करने की अनुमति दें. ऐसा करने से, ऐप्लिकेशन को बैकग्राउंड में चलने की अनुमति मिलती है. इससे बैटरी ज़्यादा खर्च होती है.\n\nऐप्लिकेशन को यह अनुमति न देने पर, इसकी मदद से सेट किए गए अलार्म और तय समय पर होने वाली कार्रवाइयों के रिमाइंडर काम नहीं करेंगे."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"शेड्यूल, अलार्म, रिमाइंडर, घड़ी"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"परेशान न करें"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"चालू करें"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\'परेशान न करें\' चालू करें"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index fbf89cb..a1c9a61 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi i podsjetnici"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Omogućite toj aplikaciji da postavlja alarme i zakazuje radnje u točno određeno vrijeme. To aplikaciji omogućuje da se izvodi u pozadini, pa je moguća dodatna potrošnja baterije.\n\nAko je to dopuštenje isključeno, postojeći alarmi i događaji zakazani putem te aplikacije neće funkcionirati."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"raspored, alarm, podsjetnik, sat"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Ne uznemiravaj"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Uključi"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Uključite opciju Ne uznemiravaj."</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 541406d..5ea4fdb 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Ébresztések és emlékeztetők"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Lehetővé teszi ennek az alkalmazásnak, hogy ébresztéseket állítson be és időérzékeny feladatokat ütemezzen. Ezzel engedélyezi az alkalmazásnak, hogy a háttérben fusson, ami megnövekedett akkumulátorhasználattal járhat.\n\nHa ez az engedély ki van kapcsolva, az alkalmazás által beállított ébresztések és ütemezett időérzékeny események nem fognak működni."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ütemezés, ébresztés, emlékeztető, óra"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Ne zavarjanak"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Bekapcsolás"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"A Ne zavarjanak mód bekapcsolása"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index ac77232..f7b51a5 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Զարթուցիչներ և հիշեցումներ"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Թույլատրել այս հավելվածին զարթուցիչներ կարգավորել և որոշակի ժամանակի համար գործողություններ պլանավորել։ Այդ դեպքում հավելվածն աշխատում է ֆոնային ռեժիմում, և արդյունքում մարտկոցի լիցքն ավելի արագ է սպառվում։\n\nԵթե այս թույլտվությունն անջատված է, հավելվածի կողմից կարգավորված զարթուցիչները և գործողությունների ժամանակացույցները չեն աշխատի։"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ժամանակացույց, զարթուցիչ, հիշեցում, ժամացույց"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Չանհանգստացնել"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Միացնել"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Միացրեք «Չանհանգստացնել» ռեժիմը"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 2297376..070c161 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -432,7 +432,7 @@
<string name="force_allow_on_external_summary" msgid="8525425782530728238">"Membuat semua aplikasi dapat ditulis ke penyimpanan eksternal, terlepas dari nilai manifes"</string>
<string name="force_resizable_activities" msgid="7143612144399959606">"Paksa aktivitas agar ukurannya dapat diubah"</string>
<string name="force_resizable_activities_summary" msgid="2490382056981583062">"Membuat semua aktivitas dapat diubah ukurannya untuk banyak jendela, terlepas dari nilai manifes."</string>
- <string name="enable_freeform_support" msgid="7599125687603914253">"Aktifkan jendela berformat bebas"</string>
+ <string name="enable_freeform_support" msgid="7599125687603914253">"Aktifkan jendela berbentuk bebas"</string>
<string name="local_backup_password_title" msgid="4631017948933578709">"Sandi cadangan desktop"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"Saat ini cadangan desktop penuh tidak dilindungi"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"Ketuk guna mengubah atau menghapus sandi untuk cadangan lengkap desktop"</string>
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarm & pengingat"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Mengizinkan aplikasi ini menyetel alarm dan menjadwalkan tindakan yang sensitif waktu. Hal ini memungkinkan aplikasi berjalan di latar belakang, sehingga mungkin menggunakan lebih banyak daya baterai.\n\nJika izin ini dinonaktifkan, alarm dan acara berbasis waktu yang dijadwalkan oleh aplikasi ini tidak akan berfungsi."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"jadwal, alarm, pengingat, jam"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Jangan Ganggu"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktifkan"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktifkan mode Jangan Ganggu"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 30d36bc..5408b50 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Vekjarar og áminningar"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Leyfa þessu forriti að stilla vekjara og áætla aðgerðir sem þurfa að eiga sér stað innan ákveðins tímaramma. Þetta leyfir forritinu að keyra í bakgrunninum sem getur notað meiri rafhlöðuorku.\n\nEf slökkt er á þessari heimild munu núverandi vekjarar og tímasettir viðburðir sem þetta forrit stillir ekki virka."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"áætlun, vekjari, áminning, klukka"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Ónáðið ekki"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Kveikja"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Kveikja á „Ónáðið ekki“"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 9dac1f6..10394f1 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Sveglie e promemoria"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Consenti a questa app di impostare sveglie e programmare azioni per orari specifici. L\'app potrà essere eseguita in background, comportando un consumo maggiore della batteria.\n\nSe questa autorizzazione viene disattivata, le sveglie esistenti e gli eventi basati sull\'orario programmati da questa app non funzioneranno."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programmare, sveglia, promemoria, orologio"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Non disturbare"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Attiva"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Attiva Non disturbare"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index e7ad1eb..fce947a 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"שעונים מעוררים ותזכורות"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ההרשאה הזו מתירה לאפליקציה להגדיר שעון מעורר ולתזמן פעולות דחופות. האפליקציה תוכל לפעול ברקע ובכך להגביר את צריכת הסוללה.\n\nאם ההרשאה מושבתת, ההתראות והאירועים מבוססי-הזמן שהוגדרו ותוזמנו על ידי האפליקציה לא יפעלו."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"תזמון, שעון מעורר, תזכורת, שעון"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"נא לא להפריע"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"הפעלה"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"הפעלת מצב נא לא להפריע"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 9848a91..41acfc0 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"アラームとリマインダー"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"アラームの設定や時間ベースのアクション設定を、このアプリに許可します。これによりアプリがバックグラウンドで実行できるようになるため、バッテリーの使用量が増えることがあります。\n\nこの権限が OFF の場合、このアプリで設定された既存のアラームと時間ベースのイベントは機能しなくなります。"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"スケジュール, アラーム, リマインダー, 時計"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"サイレント モード"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ON にする"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"サイレント モードを ON にする"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 3c03b3c..58a01a4 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"მაღვიძარები და შეხსენებები"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ნებას რთავს ამ აპს, დააყენოს მაღვიძარები და დაგეგმოს დროზე დამოკიდებული მოქმედებები. ეს საშუალებას აძლევს აპს, იმუშაოს ფონურად, რამაც შეიძლება ბატარეის ხარჯი გაზარდოს.\n\nთუ ეს ნებართვა გამორთულია, ამ აპით დაგეგმილი მაღვიძარები და დროზე დამოკიდებული მოვლენები არ იმუშავებს."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"განრიგი, მაღვიძარა, შეხსენება, საათი"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"არ შემაწუხოთ"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ჩართვა"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"„არ შემაწუხოთ“ რეჟიმის ჩართვა"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 80a1442..485120d 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Оятқыштар мен еске салғыштар"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Бұл қолданбаға оятқыштарды орнатуға және уақытқа байланысты әрекеттерді жоспарлауға рұқсат береді. Мұндайда қолданба фондық режимде жұмыс істейді, сондықтан батарея шығыны артуы мүмкін.\n\nБұл рұқсат өшірулі болса, осы қолданбада жоспарланған ағымдағы оятқыштар мен уақытқа байланысты іс-шаралар жұмыс істемейді."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"кесте, оятқыш, еске салғыш, сағат"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Мазаламау"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Қосу"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Мазаламау режимін қосу"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 4010a8b..7fbc509 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"ម៉ោងរោទ៍ និងការរំលឹក"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"អនុញ្ញាតឱ្យកម្មវិធីនេះកំណត់ម៉ោងរោទ៍ និងកំណត់កាលវិភាគសកម្មភាពដែលតម្រូវឱ្យទាន់ពេលវេលា។ ការធ្វើបែបនេះអនុញ្ញាតឱ្យកម្មវិធីនេះដំណើរការនៅផ្ទៃខាងក្រោយ ដែលអាចប្រើថ្មកាន់តែច្រើន។\n\nប្រសិនបើបិទការអនុញ្ញាតនេះ ម៉ោងរោទ៍ដែលមានស្រាប់ និងព្រឹត្តិការណ៍ផ្អែកលើពេលវេលាដែលកំណត់ដោយកម្មវិធីនេះនឹងមិនដំណើរការទេ។"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"កាលវិភាគ ម៉ោងរោទ៍ ការរំលឹក នាឡិកា"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"កុំរំខាន"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"បើក"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"បើកមុខងារកុំរំខាន"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index ea1dc7d..85075c3 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"ಅಲಾರಂಗಳು ಮತ್ತು ರಿಮೈಂಡರ್ಗಳು"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ಅಲಾರಂಗಳನ್ನು ಹೊಂದಿಸಲು ಮತ್ತು ಸಮಯ-ಸೂಕ್ಷ್ಮವಾದ ಕ್ರಿಯೆಗಳನ್ನು ನಿಗದಿಪಡಿಸಲು ಈ ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸಿ. ಇದು ಹಿನ್ನೆಲೆಯಲ್ಲಿ ರನ್ ಆಗಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ, ಅದರಿಂದ ಹೆಚ್ಚು ಬ್ಯಾಟರಿ ಬಳಕೆಯಾಗಬಹುದು.\n\nಈ ಅನುಮತಿ ಆಫ್ ಆಗಿದ್ದರೆ, ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಅಲಾರಂಗಳು ಮತ್ತು ಈ ಆ್ಯಪ್ ನಿಗದಿಪಡಿಸಿದ ಸಮಯ-ಸೂಕ್ಷ್ಮ ಈವೆಂಟ್ಗಳು ಕೆಲಸ ಮಾಡುವುದಿಲ್ಲ."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ವೇಳಾಪಟ್ಟಿ, ಅಲಾರಂ, ರಿಮೈಂಡರ್, ಗಡಿಯಾರ"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ಆನ್ ಮಾಡಿ"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಅನ್ನು ಆನ್ ಮಾಡಿ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 2a8807f..480d78f 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"알람 및 리마인더"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"이 앱이 알람을 설정하고 시간 기반 작업을 예약할 수 있도록 허용합니다. 이렇게 하면 백그라운드에서 앱 실행이 허용되어 배터리 사용량이 증가할 수 있습니다.\n\n이 권한을 사용 중지하면 이 앱에서 예약한 기존의 알람 및 시간 기반 일정이 작동하지 않습니다."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"일정 예약, 알람, 리마인더, 시계"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"방해 금지 모드"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"사용 설정"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"방해 금지 모드 사용 설정"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 8e1a1a4..1667041 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Ойготкучтар жана эстеткичтер"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Бул колдонмого ойготкучтарды коюуга жана башка аракеттерди графикке киргизүүгө уруксат бересиз. Ушуну менен колдонмо фондо иштеп, батареяны көбүрөөк сарпташы мүмкүн.\n\nЭгер бул уруксат өчүрүлсө, колдонмодогу ойготкучтар жана графикке киргизилген башка аракеттер иштебейт."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"график, ойготкуч, эстеткич, саат"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Тынчымды алба"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Күйгүзүү"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\"Тынчымды алба\" режимин күйгүзүү"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 1c7f520..2c6d6ba 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"ໂມງປຸກ ແລະ ການແຈ້ງເຕືອນ"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ອະນຸຍາດໃຫ້ແອັບນີ້ຕັ້ງໂມງປຸກ ແລະ ກຳນົດເວລາຄຳສັ່ງທີ່ເນັ້ນເລື່ອງເວລາເປັນສຳຄັນໄດ້. ນີ້ຈະເຮັດໃຫ້ແອັບເຮັດວຽກໄດ້ໃນພື້ນຫຼັງ, ເຊິ່ງອາດໃຊ້ແບັດເຕີຣີຫຼາຍຂຶ້ນ.\n\nຫາກປິດການອະນຸຍາດນີ້ໄວ້, ໂມງປຸກທີ່ມີຢູ່ກ່ອນແລ້ວ ແລະ ເຫດການທີ່ອ້າງອີງເວລາທີ່ກຳນົດໄວ້ໂດຍແອັບນີ້ຈະບໍ່ສາມາດເຮັດວຽກໄດ້."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ກຳນົດເວລາ, ໂມງປຸກ, ການແຈ້ງເຕືອນ, ໂມງ"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"ຫ້າມລົບກວນ"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ເປີດ"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"ເປີດໂໝດຫ້າມລົບກວນ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 35141d9..a6ef078 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Signalai ir priminimai"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Leiskite šiai programai nustatyti signalus ir suplanuoti veiksmus, kuriems svarbus laiko veiksnys. Dėl to programa gali veikti fone ir sunaudoti daugiau akumuliatoriaus energijos.\n\nJei šis leidimas išjungtas, šios programos suplanuoti esami signalai ir laiku pagrįsti įvykiai neveiks."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"tvarkaraštis, signalas, priminimas, laikrodis"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Netrukdymo režimas"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Įjungti"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Netrukdymo režimo įjungimas"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index dae1d2f..a1fef64 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Signāli un atgādinājumi"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Atļaujiet šai lietotnei iestatīt signālus un ieplānot darbības, kas jāveic konkrētā laikā. Tādējādi lietotne darbosies fonā un, iespējams, patērēs vairāk akumulatora enerģijas.\n\nJa šī atļauja nav piešķirta, esošie signāli un šīs lietotnes ieplānotie notikumi, kas jāizpilda konkrētā laikā, nedarbosies."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ieplānot, signāls, atgādinājums, pulkstenis"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Netraucēt"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ieslēgt"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Režīma “Netraucēt” ieslēgšana"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index a256fa7..e22f67c 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Аларми и потсетници"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Дозволете ѝ на апликацијава да поставува аларми и да закажува дејства со временски рокови. Ова овозможува апликацијата да работи во заднина и така може повеќе да ја троши батеријата.\n\nАко дозволава е исклучена, нема да функционираат постојните аларми и настаните според време закажани од апликацијава."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"закажување, аларм, потсетник, часовник"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Не вознемирувај"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Вклучи"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Исклучување на „Не вознемирувај“"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 32a779e..0b6d3fb 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"അലാറങ്ങളും റിമെെൻഡറുകളും"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"അലാറങ്ങൾ സജ്ജീകരിക്കാനും സമയപ്രാധാന്യമുള്ള പ്രവർത്തനങ്ങൾ ഷെഡ്യൂൾ ചെയ്യാനും ഈ ആപ്പിനെ അനുവദിക്കുക. പശ്ചാത്തലത്തിൽ റൺ ചെയ്യാൻ ഇത് ഈ ആപ്പിന് അനുവാദം നൽകുന്നു, ഇതിന് കൂടുതൽ ബാറ്ററി ഉപയോഗിച്ചേക്കാം.\n\nഈ അനുമതി ഓഫാണെങ്കിൽ, ഈ ആപ്പ് നിലവിൽ ഷെഡ്യൂൾ ചെയ്ത അലാറങ്ങളും സമയാധിഷ്ഠിത ഇവന്റുകളും പ്രവർത്തിക്കില്ല."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ഷെഡ്യൂൾ, അലാറം, റിമെെൻഡർ, ക്ലോക്ക്"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"ശല്യപ്പെടുത്തരുത്"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ഓണാക്കുക"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\'ശല്യപ്പെടുത്തരുത്\' ഓണാക്കുക"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 2a70e1c..1ce8b0f 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Сэрүүлэг, сануулагч"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Энэ аппад сэрүүлэг тавих болон хугацаанд мэдрэг үйлдлийн хуваарь гаргахыг зөвшөөрнө үү. Энэ нь аппад ард ажиллахыг зөвшөөрөх бөгөөд ингэснээр илүү их батарей ашиглаж магадгүй.\n\nХэрэв энэ зөвшөөрөл унтраалттай бол энэ аппын аль хэдийн тавьсан сэрүүлэг болон хуваарь гаргасан хугацаанд мэдрэг үйл явдал ажиллахгүй."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"хуваарь, сэрүүлэг, сануулагч, цаг"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Бүү саад бол"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Асаах"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Бүү саад бол горимыг асаах"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index cd32f6d..ad67ef2 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"अलार्म आणि रिमाइंडर"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"या ॲपला अलार्म सेट करण्याची किंवा वेळेनुसार संवेदनशील असलेल्या कृती शेड्युल करण्याची अनुमती द्या. हे ॲपला बॅकग्राउंडमध्ये रन होऊ देते, ज्यामुळे जास्त बॅटरी वापरली जाऊ शकते.\n\nही परवानगी बंद असल्यास, सध्याचे अलार्म आणि या ॲपद्वारे शेड्युल केलेले वेळेवर आधारित इव्हेंट काम करणार नाहीत."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"शेड्युल, अलार्म, रिमाइंडर, घड्याळ"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"व्यत्यय आणू नका"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"सुरू करा"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"व्यत्यय आणू नका सुरू करा"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index da4e53b..5bb3ba0 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Penggera & peringatan"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Benarkan apl ini menetapkan penggera dan menjadualkan tindakan yang sensitif masa. Hal ini membolehkan apl berjalan di latar, yang mungkin menggunakan lebih banyak bateri.\n\nJika kebenaran ini dimatikan, penggera sedia ada dan acara berdasarkan masa yang dijadualkan oleh apl ini tidak akan berfungsi."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"jadual, penggera, peringatan, jam"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Jangan Ganggu"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Hidupkan"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Hidupkan Jangan Ganggu"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index f9fae5a..7cce3d9 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"နှိုးစက်နှင့် သတိပေးချက်များ"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"နှိုးစက်သတ်မှတ်ရန်နှင့် အချိန်တိကျရန် လိုအပ်သည့် လုပ်ဆောင်ချက်များအတွက် အစီအစဉ်ဆွဲရန် ဤအက်ပ်ကို ခွင့်ပြုသည်။ ၎င်းက အက်ပ်ကို နောက်ခံတွင် လုပ်ဆောင်ခွင့်ပေးပြီး ဘက်ထရီပိုသုံးနိုင်သည်။\n\nဤခွင့်ပြုချက်ကို ပိတ်ထားပါက ဤအက်ပ်ဖြင့် အစီအစဉ်ဆွဲထားသော လက်ရှိနှိုးစက်နှင့် အချိန်သတ်မှတ်ထားသည့် အစီအစဉ်များ အလုပ်လုပ်တော့မည် မဟုတ်ပါ။"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"အချိန်ဇယား၊ နှိုးစက်၊ သတိပေးချက်၊ နာရီ"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"မနှောင့်ယှက်ရ"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ဖွင့်ရန်"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\'မနှောင့်ယှက်ရ\' ဖွင့်ခြင်း"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index d221b9b..c6fbea1 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmer og påminnelser"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Gi denne appen tillatelse til å angi alarmer og planlegge tidssensitive handlinger. Dette gir appen tillatelse til å kjøre i bakgrunnen, noe som kan bruke mer batteri.\n\nHvis denne tillatelsen er av, fungerer ikke eksisterende alarmer og tidsbaserte hendelser som er planlagt av denne appen."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"tidsplan, alarm, påminnelse, klokke"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Ikke forstyrr"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Slå på"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Slå på Ikke forstyrr"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 1d419ee..5d18fd3 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"अलार्म तथा रिमाइन्डर"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"यो एपलाई अलार्म सेट गर्ने र समयमै पूरा गर्नु पर्ने कारबाहीहरूको रुटिन बनाउने अनुमति दिनुहोस्। यो अनुमति दिइएको छ भने यो एप ब्याकग्राउन्डमा चल्छ र धेरै ब्याट्री खपत हुन्छ।\n\nयो अनुमति दिइएको छैन भने सेट गरिएका अलार्म बज्दैनन् र यो एपले तय गरेका गतिविधि चल्दैनन्।"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"समयतालिका, अलार्म, रिमाइन्डर, घडी"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"बाधा नपुऱ्याउनुहोस्"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"अन गर्नुहोस्"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"बाधा नपुऱ्याउनुहोस् नामक मोडलाई अन गर्नुहोस्"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 749e5da..e457376 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wekkers en herinneringen"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Sta toe dat deze app wekkers zet en tijdgevoelige acties plant. De app kan hierdoor op de achtergrond worden uitgevoerd, waardoor je misschien meer batterijlading verbruikt.\n\nAls dit recht uitstaat, werken door deze app geplande bestaande wekkers en tijdgebaseerde afspraken niet."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"plannen, schema, wekker, alarm, herinnering, klok"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Niet storen"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aanzetten"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Zet Niet storen aan."</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 5ca07c0..2f25cde 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"ଆଲାରାମ୍ ଏବଂ ରିମାଇଣ୍ଡରଗୁଡ଼ିକ"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ଏହି ଆପକୁ ଆଲାରାମ୍ ସେଟ୍ କରିବାକୁ ଏବଂ ସମୟ-ସମ୍ବେଦନଶୀଳ କାର୍ଯ୍ୟଗୁଡ଼ିକୁ ସିଡୁଲ୍ କରିବାକୁ ଅନୁମତି ଦିଅନ୍ତୁ। ଏହା ଆପକୁ ପୃଷ୍ଠପଟରେ ଚାଲିବାକୁ ଦେଇଥାଏ, ଯାହା ଅଧିକ ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରିପାରେ।\n\nଯଦି ଏହି ଅନୁମତି ବନ୍ଦ ଅଛି, ତେବେ ଏହି ଆପ୍ ଦ୍ୱାରା ସିଡୁଲ୍ କରାଯାଇଥିବା ପୂର୍ବରୁ ଥିବା ଆଲାରାମ୍ ଏବଂ ସମୟ-ଆଧାରିତ ଇଭେଣ୍ଟଗୁଡ଼ିକ କାମ କରିବ ନାହିଁ।"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ସିଡୁଲ୍, ଆଲାରାମ୍, ରିମାଇଣ୍ଡର୍, ଘଣ୍ଟା"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ଚାଲୁ କରନ୍ତୁ"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" ଅନ୍ କରନ୍ତୁ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 48db7f4..b13ef1b 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"ਅਲਾਰਮ ਅਤੇ ਰਿਮਾਈਂਡਰ"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"ਇਸ ਐਪ ਨੂੰ ਅਲਾਰਮ ਸੈੱਟ ਕਰਨ ਜਾਂ ਹੋਰ ਸਮਾਂ-ਸੰਵੇਦਨਸ਼ੀਲ ਕਾਰਵਾਈਆਂ ਨੂੰ ਨਿਯਤ ਕਰਨ ਦਿਓ। ਇਸ ਨਾਲ ਐਪ ਨੂੰ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲਣ ਦੀ ਇਜਾਜ਼ਤ ਮਿਲਦੀ ਹੈ, ਜਿਸ ਨਾਲ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਵੱਧ ਸਕਦੀ ਹੈ।\n\nਜੇ ਇਹ ਇਜਾਜ਼ਤ ਬੰਦ ਹੈ, ਤਾਂ ਇਸ ਐਪ ਰਾਹੀਂ ਨਿਯਤ ਕੀਤੇ ਮੌਜੂਦਾ ਅਲਾਰਮ ਅਤੇ ਸਮਾਂ-ਆਧਾਰਿਤ ਇਵੈਂਟ ਕੰਮ ਨਹੀਂ ਕਰਨਗੇ।"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ਸਮਾਂ-ਸੂਚੀ, ਅਲਾਰਮ, ਰਿਮਾਈਂਡਰ, ਘੜੀ"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ਚਾਲੂ ਕਰੋ"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index d0b6979..3f90774 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmy i przypomnienia"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Zezwalaj tej aplikacji na ustawianie alarmów i planowanie działań, w przypadku których czas jest istotny. Aplikacja będzie mogła działać w tle, co może zwiększyć wykorzystanie baterii.\n\nJeśli nie włączysz tego uprawnienia, istniejące alarmy i zaplanowane wydarzenia z tej aplikacji nie będą działać."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"harmonogram, alarm, przypomnienie, zegar"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Nie przeszkadzać"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Włącz"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Włącz tryb Nie przeszkadzać"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 6eaa518..00375b0 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações com hora marcada. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarme, lembrete, relógio"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Não perturbe"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o Não perturbe"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index a411dc8..97d2848 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permita que a app defina alarmes e agende ações com um horário específico. Esta ação permite que a app seja executada em segundo plano, o que pode usar mais bateria.\n\nSe esta autorização estiver desativada, os alarmes existentes e os eventos com base no tempo agendados por esta app não funcionam."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"agendar, alarme, lembrete, relógio"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Não incomodar"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o modo Não incomodar"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 6eaa518..00375b0 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações com hora marcada. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarme, lembrete, relógio"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Não perturbe"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o Não perturbe"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 71f0d2f..900851e 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarme și mementouri"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite acestei aplicații să seteze alarme și să planifice acțiuni care trebuie realizate în timp scurt. Astfel, aplicația poate să ruleze în fundal, ceea ce ar putea crește consumul de baterie.\n\nDacă permisiunea este dezactivată, alarmele și evenimentele dependente de timp planificate de aplicație nu vor funcționa."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programare, alarmă, memento, ceas"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Nu deranja"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activează"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activează Nu deranja"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 0c9c9cf..db4be66 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Будильники и напоминания"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Вы можете разрешить этому приложению устанавливать будильники и планировать запуск действий в определенное время. В этом случае оно будет работать в фоновом режиме и быстрее расходовать заряд батареи.\n\nЕсли отключить это разрешение, текущие будильники и созданные приложением события перестанут запускаться."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"установить, будильник, напоминание, часы"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Не беспокоить"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Включить"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Включите режим \"Не беспокоить\""</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 0bba018..d9df5eb 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"එලාම සහ සිහිකැඳවීම්"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"එලාම සැකසීමට සහ කාල සංවේදී ක්රියා කාලසටහන්ගත කිරීමට මෙම යෙදුමට ඉඩ දෙන්න. මෙය පසුබිමේ ධාවනය වීමට යෙදුමට ඉඩ දෙයි, එය වැඩි බැටරිය වැඩියෙන් භාවිත කළ හැකිය.\n\nමෙම අවසරය ක්රියාවිරහිත නම්, මෙම යෙදුම මඟින් සැලසුම් කර ඇති තිබෙන එලාම සහ වේලාව පදනම් කර ගත් සිදුවීම් ක්රියා නොකරනු ඇත."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"කාල සටහන, එලාමය, සිහිකැඳවීම, ඔරලෝසුව"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"බාධා නොකරන්න"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ක්රියාත්මක කරන්න"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"බාධා නොකරන්න ක්රියාත්මක කරන්න"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index acb528f1..c690a19 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Budíky a pripomenutia"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Povoľte tejto aplikácii nastavovať budíky a plánovať akcie s časovým obmedzením. Aplikácii to umožní pracovať na pozadí, čo môže zvýšiť spotrebu batérie.\n\nAk je toto povolenie vypnuté, existujúce budíky a udalosti s časovým obmedzením naplánované touto aplikáciou nebudú fungovať."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"plán, budík, pripomenutie, hodiny"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Režim bez vyrušení"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Zapnúť"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Zapnite režim bez vyrušení"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index ff11a7a..7fa5ed1 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi in opomniki"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Tej aplikaciji dovolite nastavljanje alarmov in načrtovanje časovno občutljivih dejanj. S tem aplikaciji omogočite izvajanje v ozadju, kar bo morda povečalo porabo energije baterije.\n\nČe je to dovoljenje izklopljeno, obstoječi alarmi in časovno občutljivi dogodki, ki jih nastavi ta aplikacija, ne bodo delovali."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"načrtovanje, urnik, alarm, opomnik, ura"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Ne moti"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Vklopi"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Vklop načina »Ne moti«"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index f0d1ac5..b64c8fd 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmet dhe alarmet rikujtuese"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Lejo që ky aplikacion të caktojë alarmet dhe të planifikojë veprime që kanë një afat të caktuar. Kjo mundëson që aplikacioni të ekzekutohet në sfond, gjë që mund të përdorë më shumë bateri.\n\nNëse kjo leje është caktuar si joaktive, alarmet ekzistuese dhe ngjarjet në bazë kohore të planifikuara nga ky aplikacion nuk do të funksionojnë."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"planifiko, alarm, alarm rikujtues, ora"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Mos shqetëso"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktivizo"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktivizo \"Mos shqetëso\""</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 557e95b..f9001a8 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Аларми и подсетници"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Омогућите овој апликацији да подешава аларме и заказује временски осетљиве радње. То омогућава да апликација буде покренута у позадини, што може да троши више батерије.\n\nАко је ова дозвола искључена, постојећи аларми и догађаји засновани на времену заказани помоћу ове апликације неће радити."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"заказати, аларм, подсетник, сат"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Не узнемиравај"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Укључи"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Укључите режим Не узнемиравај"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 2404dc2..4ca4835 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarm och påminnelser"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Tillåt att den här appen ställer in alarm och schemalägger tidskänsliga åtgärder. Om du tillåter detta kan appen köras i bakgrunden, vilket kan dra mer batteri.\n\nOm behörigheten är inaktiverad fungerar inte befintliga alarm och tidsbaserade händelser som schemalagts av den här appen."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"schema, alarm, påminnelse, klocka"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Stör ej"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktivera"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktivera Stör ej."</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 03ddecd..3198d0a 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Kengele na vikumbusho"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Ruhusu programu hii iweke kengele na ratiba za vitendo vingine vinavyotegemea wakati. Hatua hii inairuhusu programu itumike chinichini, hali inayoweza kutumia chaji nyingi ya betri.\n\nIkiwa ruhusa hii itazimwa, kengele zilizopo na ratiba za vitendo vinavyotegemea wakati zilizowekwa na programu hii hazitafanya kazi."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ratiba, kengele, kikumbusho, saa"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Usinisumbue"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Washa"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Washa kipengele cha Usinisumbue"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index d3f3c96..108ddce 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"அலாரங்கள் & நினைவூட்டல்கள்"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"அலாரங்களை அமைக்கவும் குறிப்பிட்ட கால இடைவெளியில் செயல்களைத் திட்டமிடவும் இந்த ஆப்ஸை அனுமதிக்கும். இது ஆப்ஸ் பின்னணியில் இயங்குவதை அனுமதிக்கும், இதற்காக அதிக பேட்டரியைப் பயன்படுத்தக்கூடும்.\n\nஇந்த அனுமதி முடக்கப்பட்டிருந்தால் இந்த ஆப்ஸ் மூலம் திட்டமிடப்பட்ட ஏற்கெனவே அமைத்த அலாரங்களும் நேர அடிப்படையிலான நிகழ்வுகளும் வேலை செய்யாது."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"திட்டமிடல், அலாரம், நினைவூட்டல், கடிகாரம்"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"தொந்தரவு செய்யாதே"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ஆன் செய்"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"தொந்தரவு செய்ய வேண்டாம் என்பதை ஆன் செய்யும்"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 0aa94a6..4811594 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"అలారాలు & రిమైండర్లు"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"అలారాలను సెట్ చేయడానికి, టైమ్-సెన్సిటివ్ చర్యలను షెడ్యూల్ చేయడానికి ఈ యాప్ను అనుమతించండి. ఇది యాప్ను బ్యాక్గ్రౌండ్లో రన్ అవడానికి అనుమతిస్తుంది, ఇది ఎక్కువ బ్యాటరీని ఉపయోగించవచ్చు.\n\nఈ అనుమతిని ఆఫ్ చేస్తే, ఈ యాప్ ద్వారా షెడ్యూల్ చేసినటువంటి ఇప్పటికే ఉన్న అలారాలు, టైమ్-ఆధారిత ఈవెంట్లు పనిచేయవు."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"షెడ్యూల్, అలారం, రిమైండర్, గడియారం"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"అంతరాయం కలిగించవద్దు"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ఆన్ చేయండి"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"అంతరాయం కలిగించవద్దును ఆన్ చేయండి"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 970e456..b332154 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"การปลุกและการช่วยเตือน"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"อนุญาตให้แอปนี้ตั้งปลุกและกำหนดเวลาการดำเนินการที่ต้องคำนึงถึงเวลาเป็นสำคัญ สิทธิ์นี้ช่วยให้แอปทำงานในเบื้องหลังได้ จึงอาจทำให้ใช้แบตเตอรี่มากขึ้น\n\nหากปิดใช้สิทธิ์นี้ การปลุกที่มีอยู่และกิจกรรมที่ต้องคำนึงถึงเวลาเป็นสำคัญซึ่งแอปนี้กำหนดเวลาไว้จะไม่ทำงาน"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"กำหนดเวลา การปลุก การช่วยเตือน นาฬิกา"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"ห้ามรบกวน"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"เปิด"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"เปิด \"ห้ามรบกวน\""</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 0ba4a7b..cf88980 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Mga alarm at paalala"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Payagan ang app na ito na magtakda ng mga alarm at mag-iskedyul ng mga pagkilos na may limitadong oras. Papayagan nitong tumakbo ang app sa background, na posibleng gumamit ng mas maraming baterya.\n\nKung naka-off ang pahintulot na ito, hindi gagana ang mga kasalukuyang alarm at event na nakabatay sa oras na naiskedyul ng app na ito."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"iskedyul, alarm, paalala, orasan"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Huwag Istorbohin"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"I-on"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"I-on ang Huwag Istorbohin"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 0506480..6cdfa2e 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmlar ve hatırlatıcılar"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Bu uygulamanın alarm kurmasına ve zamana bağlı işlemler programlamasına izin verin. Bu izin, uygulamanın arka planda çalışmasına olanak sağlayarak daha fazla pil harcanmasına neden olabilir.\n\nBu izin verilmezse bu uygulama tarafından programlanmış mevcut alarmlar ve zamana bağlı etkinlikler çalışmaz."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"program, alarm, hatırlatıcı, saat"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Rahatsız Etmeyin"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aç"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Rahatsız Etmeyin\'i açın"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 0ee73bd..7abd4a8 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Будильники й нагадування"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Дозволити цьому додатку налаштовувати будильники й створювати розклад дій. Додаток зможе працювати у фоновому режимі й використовувати більше заряду акумулятора.\n\nЯкщо вимкнути такий дозвіл, наявні будильники й дії, створені цим додатком, не працюватимуть."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"запланувати, будильник, нагадування, годинник"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Не турбувати"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Увімкнути"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Увімкнути режим \"Не турбувати\""</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 3678410..bf7ac58 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"الارمز اور یاد دہانیاں"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"اس ایپ کو الارمز سیٹ کرنے اور وقت کے لحاظ سے حساس کارروائیوں کو شیڈول کرنے کی اجازت دیں۔ اس سے ایپ کو پس منظر میں چلنے کی اجازت ملتی ہے، جس میں زیادہ بیٹری استعمال ہو سکتی ہے۔\n\n اگر یہ اجازت آف ہے تو موجودہ الارمز اور اس ایپ کے ذریعے شیڈول کردہ وقت پر مبنی ایونٹس کام نہیں کریں گے۔"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"شیڈول، الارم، یاد دہانی، گھڑی"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"ڈسٹرب نہ کریں"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"آن کریں"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\'ڈسٹرب نہ کریں\' کو آن کریں"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 893cd57..2418053 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Signal va eslatmalar"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Bu ilovaga signal oʻrnatish va vaqtga asoslangan amallarni rejalashtirishga ruxsat berish. Bunda ilovaga orqa fonda ishlashiga imkon beriladi, shu sababli batareya ortiqcha sarflanishi mumkin.\n\nAgar bu ruxsat oʻchirilsa, ushbu ilova tomonidan rejalashtirilgan mavjud signallar va vaqtga asoslangan tadbirlar ishlamaydi."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"reja, signal, eslatma, soat"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Bezovta qilinmasin"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Yoqish"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Bezovta qilinmasin rejimini yoqing"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 101d352..15839b8 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Chuông báo và lời nhắc"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Cho phép ứng dụng này đặt chuông báo và lên lịch các hành động cần chính xác về thời gian. Tùy chọn này cho phép ứng dụng chạy ở chế độ nền và có thể làm tiêu hao nhiều pin.\n\nNếu không cấp quyền này, các chuông báo và sự kiện theo thời gian do ứng dụng này lên lịch sẽ không hoạt động."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"lịch biểu, chuông báo, lời nhắc, đồng hồ"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Không làm phiền"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Bật"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Bật chế độ Không làm phiền"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 88e67f6..a2fd4ea 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"闹钟和提醒"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"允许该应用设置闹钟以及安排在特定时间执行某些操作。这项权限开启后,该应用将在后台运行,可能会消耗更多电池电量。\n\n如果您关闭此权限,该应用设置的现有闹钟将不会响起,而且该应用安排在特定时间执行的现有活动也不会执行。"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"设置, 闹钟, 提醒, 时钟, schedule, alarm, reminder, clock"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"勿扰模式"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"开启"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"开启勿扰模式"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 6a35ece..bcf624e4 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"鬧鐘和提醒"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"允許此應用程式設定鬧鐘及安排具時效性的操作。這讓應用程式在背景中執行,因此可能會較耗電。\n\n如果關閉此權限,此應用程式將不會在預定時間響起已設定的鬧鐘,亦不會就特定時間的活動傳送通知。"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"日程表, 鬧鐘, 提醒, 時鐘"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"請勿騷擾"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"開啟"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"開啟「請勿騷擾」模式"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 9d00a05..58a19793 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"鬧鐘和提醒"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"允許這個應用程式設定鬧鐘及安排有時效性的動作。之後應用程式可以在背景執行,並可能耗用較多電量。\n\n如果關閉這項權限,這個應用程式設定的現有鬧鐘將不會響起,系統也無法在預定的時間發出活動提醒。"</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"時間表, 鬧鐘, 提醒, 時鐘"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"零打擾"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"開啟"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"開啟「零打擾」模式"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 0c326146..28b9b05 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -564,6 +564,8 @@
<string name="alarms_and_reminders_title" msgid="8819933264635406032">"Ama-alamu nezikhumbuzi"</string>
<string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Vumela le app isethe ama-alamu futhi ushejule izenzo zesikhathi esizwelayo. Lokhu kuvumela i-app iqhubeke ngemuva okungasebenzisa ibhethri lakho eliningi.\n\nUma le mvume ivaliwe, ama-alamu asele nemicimbi esekelwe esikhathini ehlelwe yile app ngeke kusebenze."</string>
<string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"ishejuli, i-alamu, isikhumbuzi, iwashi"</string>
+ <!-- no translation found for zen_mode_do_not_disturb_name (6798711401734798283) -->
+ <skip />
<string name="zen_mode_settings_title" msgid="7374070457626419755">"Ungaphazamisi"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Vula"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Vula ukungaphazamisi"</string>
diff --git a/packages/SettingsLib/res/values/config.xml b/packages/SettingsLib/res/values/config.xml
index 68b81db..3c3de04 100644
--- a/packages/SettingsLib/res/values/config.xml
+++ b/packages/SettingsLib/res/values/config.xml
@@ -31,4 +31,14 @@
<!-- Control whether status bar should distinguish HSPA data icon form UMTS
data icon on devices -->
<bool name="config_hspa_data_distinguishable">false</bool>
+
+ <!-- Edit User avatar explicit package name -->
+ <string name="config_avatar_picker_package" translatable="false">
+ com.android.avatarpicker
+ </string>
+
+ <!-- Edit User avatar explicit activity class -->
+ <string name="config_avatar_picker_class" translatable="false">
+ com.android.avatarpicker.ui.AvatarPickerActivity
+ </string>
</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index b02b0c4..1e58335 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -495,7 +495,7 @@
|| packageName.equals(sServicesSystemSharedLibPackageName)
|| packageName.equals(sSharedSystemSharedLibPackageName)
|| packageName.equals(PrintManager.PRINT_SPOOLER_PACKAGE_NAME)
- || (updateServiceV2() && packageName.equals(getDefaultWebViewPackageName()))
+ || (updateServiceV2() && packageName.equals(getDefaultWebViewPackageName(pm)))
|| isDeviceProvisioningPackage(resources, packageName);
}
@@ -511,7 +511,7 @@
/** Fetch the package name of the default WebView provider. */
@Nullable
- private static String getDefaultWebViewPackageName() {
+ private static String getDefaultWebViewPackageName(PackageManager pm) {
if (sDefaultWebViewPackageName != null) {
return sDefaultWebViewPackageName;
}
@@ -519,9 +519,10 @@
WebViewProviderInfo provider = null;
if (android.webkit.Flags.updateServiceIpcWrapper()) {
- WebViewUpdateManager manager = WebViewUpdateManager.getInstance();
- if (manager != null) {
- provider = manager.getDefaultWebViewPackage();
+ if (pm.hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
+ // WebViewUpdateManager.getInstance() will not return null on devices with
+ // FEATURE_WEBVIEW.
+ provider = WebViewUpdateManager.getInstance().getDefaultWebViewPackage();
}
} else {
try {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index 0ffb763..616ab07 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -104,6 +104,22 @@
/**
* @param context to access resources from
* @param cachedDevice to get class from
+ * @return pair containing the drawable and the description of the type of the device. The type
+ * could either derived from metadata or CoD.
+ */
+ public static Pair<Drawable, String> getDerivedBtClassDrawableWithDescription(
+ Context context, CachedBluetoothDevice cachedDevice) {
+ return BluetoothUtils.isAdvancedUntetheredDevice(cachedDevice.getDevice())
+ ? new Pair<>(
+ getBluetoothDrawable(
+ context, com.android.internal.R.drawable.ic_bt_headphones_a2dp),
+ context.getString(R.string.bluetooth_talkback_headphone))
+ : BluetoothUtils.getBtClassDrawableWithDescription(context, cachedDevice);
+ }
+
+ /**
+ * @param context to access resources from
+ * @param cachedDevice to get class from
* @return pair containing the drawable and the description of the Bluetooth class of the
* device.
*/
@@ -731,9 +747,7 @@
int broadcastId = broadcast.getLatestBroadcastId();
return !sourceList.isEmpty()
&& broadcastId != UNKNOWN_VALUE_PLACEHOLDER
- && sourceList.stream()
- .anyMatch(
- source -> isSourceMatched(source, broadcastId));
+ && sourceList.stream().anyMatch(source -> isSourceMatched(source, broadcastId));
}
/** Checks the connectivity status based on the provided broadcast receive state. */
@@ -1030,8 +1044,7 @@
cachedDevice.getAddress());
break;
case BluetoothProfile.LE_AUDIO:
- if (audioDeviceCategory
- == AudioManager.AUDIO_DEVICE_CATEGORY_SPEAKER) {
+ if (audioDeviceCategory == AudioManager.AUDIO_DEVICE_CATEGORY_SPEAKER) {
saDevice =
new AudioDeviceAttributes(
AudioDeviceAttributes.ROLE_OUTPUT,
diff --git a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingContract.kt
similarity index 71%
copy from services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
copy to packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingContract.kt
index 502337c..65adec4 100644
--- a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingContract.kt
@@ -14,11 +14,9 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.settingslib.bluetooth.devicesettings
-class BinaryStatePowerStatsLayout extends EnergyConsumerPowerStatsLayout {
- BinaryStatePowerStatsLayout() {
- addDeviceSectionUsageDuration();
- addUidSectionUsageDuration();
- }
+/** The contract between the device settings provider services and Settings. */
+object DeviceSettingContract {
+ const val INVISIBLE_PROFILES = "INVISIBLE_PROFILES"
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt
index 457d6a3..769b6e6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt
@@ -22,6 +22,7 @@
import com.android.settingslib.bluetooth.CachedBluetoothDevice
import com.android.settingslib.bluetooth.devicesettings.ActionSwitchPreference
import com.android.settingslib.bluetooth.devicesettings.DeviceSetting
+import com.android.settingslib.bluetooth.devicesettings.DeviceSettingContract
import com.android.settingslib.bluetooth.devicesettings.DeviceSettingId
import com.android.settingslib.bluetooth.devicesettings.DeviceSettingItem
import com.android.settingslib.bluetooth.devicesettings.DeviceSettingsConfig
@@ -30,6 +31,9 @@
import com.android.settingslib.bluetooth.devicesettings.MultiTogglePreference
import com.android.settingslib.bluetooth.devicesettings.ToggleInfo
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel
+import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel.AppProvidedItem
+import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel.BuiltinItem.BluetoothProfilesItem
+import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel.BuiltinItem.CommonBuiltinItem
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigModel
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingIcon
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingModel
@@ -103,9 +107,18 @@
private fun DeviceSettingItem.toModel(): DeviceSettingConfigItemModel {
return if (!TextUtils.isEmpty(preferenceKey)) {
- DeviceSettingConfigItemModel.BuiltinItem(settingId, preferenceKey!!)
+ if (settingId == DeviceSettingId.DEVICE_SETTING_ID_BLUETOOTH_PROFILES) {
+ BluetoothProfilesItem(
+ settingId,
+ preferenceKey!!,
+ extras.getStringArrayList(DeviceSettingContract.INVISIBLE_PROFILES)
+ ?: emptyList()
+ )
+ } else {
+ CommonBuiltinItem(settingId, preferenceKey!!)
+ }
} else {
- DeviceSettingConfigItemModel.AppProvidedItem(settingId)
+ AppProvidedItem(settingId)
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingServiceConnection.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingServiceConnection.kt
index 33beb06..7eae5b2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingServiceConnection.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingServiceConnection.kt
@@ -23,6 +23,7 @@
import android.content.ServiceConnection
import android.os.IBinder
import android.os.IInterface
+import android.text.TextUtils
import android.util.Log
import com.android.settingslib.bluetooth.BluetoothUtils
import com.android.settingslib.bluetooth.CachedBluetoothDevice
@@ -84,6 +85,10 @@
}
setAction(intentAction)
}
+
+ fun isValid(): Boolean {
+ return !TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(intentAction)
+ }
}
private var isServiceEnabled =
@@ -96,7 +101,8 @@
} else if (allStatus.all { it is ServiceConnectionStatus.Connected }) {
allStatus
.filterIsInstance<
- ServiceConnectionStatus.Connected<IDeviceSettingsProviderService>
+ ServiceConnectionStatus.Connected<
+ IDeviceSettingsProviderService>
>()
.all { it.service.serviceStatus?.enabled == true }
} else {
@@ -215,6 +221,7 @@
)
}
}
+ ?.filter { it.isValid() }
?.distinct()
?.associateBy(
{ it },
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt
index c1ac763..08fb3fb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt
@@ -36,10 +36,23 @@
@DeviceSettingId val settingId: Int
/** A built-in item in Settings. */
- data class BuiltinItem(
- @DeviceSettingId override val settingId: Int,
- val preferenceKey: String?
- ) : DeviceSettingConfigItemModel
+ sealed interface BuiltinItem : DeviceSettingConfigItemModel {
+ @DeviceSettingId override val settingId: Int
+ val preferenceKey: String
+
+ /** A general built-in item in Settings. */
+ data class CommonBuiltinItem(
+ @DeviceSettingId override val settingId: Int,
+ override val preferenceKey: String,
+ ) : BuiltinItem
+
+ /** A bluetooth profiles in Settings. */
+ data class BluetoothProfilesItem(
+ @DeviceSettingId override val settingId: Int,
+ override val preferenceKey: String,
+ val invisibleProfiles: List<String>,
+ ) : BuiltinItem
+ }
/** A remote item provided by other apps. */
data class AppProvidedItem(@DeviceSettingId override val settingId: Int) :
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt b/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt
index 043219a..c686708 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/data/repository/FakeZenModeRepository.kt
@@ -61,6 +61,10 @@
mutableModesFlow.value += zenModes
}
+ fun addMode(mode: ZenMode) {
+ mutableModesFlow.value += mode
+ }
+
fun addMode(id: String, @AutomaticZenRule.Type type: Int = AutomaticZenRule.TYPE_UNKNOWN,
active: Boolean = false) {
mutableModesFlow.value += newMode(id, type, active)
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
index d0661fa..7b2a284 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
@@ -69,23 +69,6 @@
static final String MANUAL_DND_MODE_ID = ZenModeConfig.MANUAL_RULE_ID;
static final String TEMP_NEW_MODE_ID = "temp_new_mode";
- // Must match com.android.server.notification.ZenModeHelper#applyCustomPolicy.
- static final ZenPolicy POLICY_INTERRUPTION_FILTER_ALARMS =
- new ZenPolicy.Builder()
- .disallowAllSounds()
- .allowAlarms(true)
- .allowMedia(true)
- .allowPriorityChannels(false)
- .build();
-
- // Must match com.android.server.notification.ZenModeHelper#applyCustomPolicy.
- static final ZenPolicy POLICY_INTERRUPTION_FILTER_NONE =
- new ZenPolicy.Builder()
- .disallowAllSounds()
- .hideAllVisualEffects()
- .allowPriorityChannels(false)
- .build();
-
private static final Comparator<Integer> PRIORITIZED_TYPE_COMPARATOR = new Comparator<>() {
private static final ImmutableList</* @AutomaticZenRule.Type */ Integer>
@@ -320,10 +303,12 @@
return requireNonNull(mRule.getZenPolicy());
case NotificationManager.INTERRUPTION_FILTER_ALARMS:
- return POLICY_INTERRUPTION_FILTER_ALARMS;
+ return new ZenPolicy.Builder(ZenModeConfig.getDefaultZenPolicy()).build()
+ .overwrittenWith(ZenPolicy.getBasePolicyInterruptionFilterAlarms());
case NotificationManager.INTERRUPTION_FILTER_NONE:
- return POLICY_INTERRUPTION_FILTER_NONE;
+ return new ZenPolicy.Builder(ZenModeConfig.getDefaultZenPolicy()).build()
+ .overwrittenWith(ZenPolicy.getBasePolicyInterruptionFilterNone());
case NotificationManager.INTERRUPTION_FILTER_UNKNOWN:
default:
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java b/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
index cdc3f12..f38e91a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
@@ -32,6 +32,7 @@
import com.android.internal.util.UserIcons;
import com.android.settingslib.drawable.CircleFramedDrawable;
+import com.android.settingslib.R;
import com.android.settingslib.utils.ThreadUtils;
import com.google.common.util.concurrent.FutureCallback;
@@ -132,6 +133,13 @@
intent.addCategory(Intent.CATEGORY_DEFAULT);
if (Flags.avatarSync()) {
intent.putExtra(EXTRA_IS_USER_NEW, isUserNew);
+ // Fix vulnerability b/341688848 by explicitly set the class name of avatar picker.
+ if (Flags.fixAvatarCrossUserLeak()) {
+ final String packageName =
+ mActivity.getString(R.string.config_avatar_picker_package);
+ final String className = mActivity.getString(R.string.config_avatar_picker_class);
+ intent.setClassName(packageName, className);
+ }
} else {
// SettingsLib is used by multiple apps therefore we need to know out of all apps
// using settingsLib which one is the one we return value to.
diff --git a/packages/SettingsLib/src/com/android/settingslib/view/accessibility/data/repository/CaptioningRepository.kt b/packages/SettingsLib/src/com/android/settingslib/view/accessibility/data/repository/CaptioningRepository.kt
deleted file mode 100644
index 0b71d25..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/view/accessibility/data/repository/CaptioningRepository.kt
+++ /dev/null
@@ -1,113 +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.settingslib.view.accessibility.data.repository
-
-import android.view.accessibility.CaptioningManager
-import kotlin.coroutines.CoroutineContext
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.channels.ProducerScope
-import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.SharedFlow
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.callbackFlow
-import kotlinx.coroutines.flow.filterIsInstance
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.onStart
-import kotlinx.coroutines.flow.shareIn
-import kotlinx.coroutines.flow.stateIn
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-
-interface CaptioningRepository {
-
- /** The system audio caption enabled state. */
- val isSystemAudioCaptioningEnabled: StateFlow<Boolean>
-
- /** The system audio caption UI enabled state. */
- val isSystemAudioCaptioningUiEnabled: StateFlow<Boolean>
-
- /** Sets [isSystemAudioCaptioningEnabled]. */
- suspend fun setIsSystemAudioCaptioningEnabled(isEnabled: Boolean)
-}
-
-class CaptioningRepositoryImpl(
- private val captioningManager: CaptioningManager,
- private val backgroundCoroutineContext: CoroutineContext,
- coroutineScope: CoroutineScope,
-) : CaptioningRepository {
-
- private val captioningChanges: SharedFlow<CaptioningChange> =
- callbackFlow {
- val listener = CaptioningChangeProducingListener(this)
- captioningManager.addCaptioningChangeListener(listener)
- awaitClose { captioningManager.removeCaptioningChangeListener(listener) }
- }
- .shareIn(coroutineScope, SharingStarted.WhileSubscribed(), replay = 0)
-
- override val isSystemAudioCaptioningEnabled: StateFlow<Boolean> =
- captioningChanges
- .filterIsInstance(CaptioningChange.IsSystemAudioCaptioningEnabled::class)
- .map { it.isEnabled }
- .onStart { emit(captioningManager.isSystemAudioCaptioningEnabled) }
- .stateIn(
- coroutineScope,
- SharingStarted.WhileSubscribed(),
- captioningManager.isSystemAudioCaptioningEnabled,
- )
-
- override val isSystemAudioCaptioningUiEnabled: StateFlow<Boolean> =
- captioningChanges
- .filterIsInstance(CaptioningChange.IsSystemUICaptioningEnabled::class)
- .map { it.isEnabled }
- .onStart { emit(captioningManager.isSystemAudioCaptioningUiEnabled) }
- .stateIn(
- coroutineScope,
- SharingStarted.WhileSubscribed(),
- captioningManager.isSystemAudioCaptioningUiEnabled,
- )
-
- override suspend fun setIsSystemAudioCaptioningEnabled(isEnabled: Boolean) {
- withContext(backgroundCoroutineContext) {
- captioningManager.isSystemAudioCaptioningEnabled = isEnabled
- }
- }
-
- private sealed interface CaptioningChange {
-
- data class IsSystemAudioCaptioningEnabled(val isEnabled: Boolean) : CaptioningChange
-
- data class IsSystemUICaptioningEnabled(val isEnabled: Boolean) : CaptioningChange
- }
-
- private class CaptioningChangeProducingListener(
- private val scope: ProducerScope<CaptioningChange>
- ) : CaptioningManager.CaptioningChangeListener() {
-
- override fun onSystemAudioCaptioningChanged(enabled: Boolean) {
- emitChange(CaptioningChange.IsSystemAudioCaptioningEnabled(enabled))
- }
-
- override fun onSystemAudioCaptioningUiChanged(enabled: Boolean) {
- emitChange(CaptioningChange.IsSystemUICaptioningEnabled(enabled))
- }
-
- private fun emitChange(change: CaptioningChange) {
- scope.launch { scope.send(change) }
- }
- }
-}
diff --git a/packages/SettingsLib/src/com/android/settingslib/view/accessibility/domain/interactor/CaptioningInteractor.kt b/packages/SettingsLib/src/com/android/settingslib/view/accessibility/domain/interactor/CaptioningInteractor.kt
deleted file mode 100644
index 858c8b3..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/view/accessibility/domain/interactor/CaptioningInteractor.kt
+++ /dev/null
@@ -1,32 +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.settingslib.view.accessibility.domain.interactor
-
-import com.android.settingslib.view.accessibility.data.repository.CaptioningRepository
-import kotlinx.coroutines.flow.StateFlow
-
-class CaptioningInteractor(private val repository: CaptioningRepository) {
-
- val isSystemAudioCaptioningEnabled: StateFlow<Boolean>
- get() = repository.isSystemAudioCaptioningEnabled
-
- val isSystemAudioCaptioningUiEnabled: StateFlow<Boolean>
- get() = repository.isSystemAudioCaptioningUiEnabled
-
- suspend fun setIsSystemAudioCaptioningEnabled(enabled: Boolean) =
- repository.setIsSystemAudioCaptioningEnabled(enabled)
-}
diff --git a/packages/SettingsLib/tests/integ/Android.bp b/packages/SettingsLib/tests/integ/Android.bp
index 33d23a3..48a1af6 100644
--- a/packages/SettingsLib/tests/integ/Android.bp
+++ b/packages/SettingsLib/tests/integ/Android.bp
@@ -72,3 +72,10 @@
dxflags: ["--multi-dex"],
manifest: "AndroidManifest.xml",
}
+
+test_module_config {
+ name: "SettingsLibTests_settingslib_users",
+ base: "SettingsLibTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.settingslib.users."],
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
index a0e764a..8eedb35 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
@@ -46,6 +46,7 @@
import android.provider.Settings;
import android.util.Pair;
+import com.android.internal.R;
import com.android.settingslib.widget.AdaptiveIcon;
import com.google.common.collect.ImmutableList;
@@ -118,6 +119,34 @@
}
@Test
+ public void
+ getDerivedBtClassDrawableWithDescription_isAdvancedUntetheredDevice_returnHeadset() {
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
+ .thenReturn(BOOL_METADATA.getBytes());
+ when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
+ Pair<Drawable, String> pair =
+ BluetoothUtils.getDerivedBtClassDrawableWithDescription(
+ mContext, mCachedBluetoothDevice);
+
+ verify(mContext).getDrawable(R.drawable.ic_bt_headphones_a2dp);
+ }
+
+ @Test
+ public void
+ getDerivedBtClassDrawableWithDescription_notAdvancedUntetheredDevice_returnPhone() {
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
+ .thenReturn("false".getBytes());
+ when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
+ when(mCachedBluetoothDevice.getBtClass().getMajorDeviceClass())
+ .thenReturn(BluetoothClass.Device.Major.PHONE);
+ Pair<Drawable, String> pair =
+ BluetoothUtils.getDerivedBtClassDrawableWithDescription(
+ mContext, mCachedBluetoothDevice);
+
+ verify(mContext).getDrawable(R.drawable.ic_phone);
+ }
+
+ @Test
public void getBtClassDrawableWithDescription_typePhone_returnPhoneDrawable() {
when(mCachedBluetoothDevice.getBtClass().getMajorDeviceClass())
.thenReturn(BluetoothClass.Device.Major.PHONE);
@@ -681,8 +710,8 @@
when(mAssistant.getAllSources(mBluetoothDevice)).thenReturn(sourceList);
assertThat(
- BluetoothUtils.hasActiveLocalBroadcastSourceForBtDevice(
- mBluetoothDevice, mLocalBluetoothManager))
+ BluetoothUtils.hasActiveLocalBroadcastSourceForBtDevice(
+ mBluetoothDevice, mLocalBluetoothManager))
.isTrue();
}
@@ -694,12 +723,11 @@
when(mAssistant.getAllSources(mBluetoothDevice)).thenReturn(sourceList);
assertThat(
- BluetoothUtils.hasActiveLocalBroadcastSourceForBtDevice(
- mBluetoothDevice, mLocalBluetoothManager))
+ BluetoothUtils.hasActiveLocalBroadcastSourceForBtDevice(
+ mBluetoothDevice, mLocalBluetoothManager))
.isFalse();
}
-
@Test
public void isAvailableHearingDevice_isConnectedHearingAid_returnTure() {
when(mCachedBluetoothDevice.isConnectedHearingAidDevice()).thenReturn(true);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt
index ce155b5..81b5634 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt
@@ -91,7 +91,9 @@
`when`(cachedDevice.address).thenReturn(BLUETOOTH_ADDRESS)
`when`(
bluetoothDevice.getMetadata(
- DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
+ DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS
+ )
+ )
.thenReturn(BLUETOOTH_DEVICE_METADATA.toByteArray())
`when`(configService.queryLocalInterface(anyString())).thenReturn(configService)
@@ -114,7 +116,8 @@
connection.onServiceConnected(
ComponentName(
SETTING_PROVIDER_SERVICE_PACKAGE_NAME_1,
- SETTING_PROVIDER_SERVICE_CLASS_NAME_1),
+ SETTING_PROVIDER_SERVICE_CLASS_NAME_1,
+ ),
settingProviderService1,
)
SETTING_PROVIDER_SERVICE_INTENT_ACTION_2 ->
@@ -146,16 +149,24 @@
fun getDeviceSettingsConfig_withMetadata_success() {
testScope.runTest {
`when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG)
- `when`(settingProviderService1.serviceStatus).thenReturn(
- DeviceSettingsProviderServiceStatus(true)
- )
- `when`(settingProviderService2.serviceStatus).thenReturn(
- DeviceSettingsProviderServiceStatus(true)
- )
+ `when`(settingProviderService1.serviceStatus)
+ .thenReturn(DeviceSettingsProviderServiceStatus(true))
+ `when`(settingProviderService2.serviceStatus)
+ .thenReturn(DeviceSettingsProviderServiceStatus(true))
val config = underTest.getDeviceSettingsConfig(cachedDevice)
assertConfig(config!!, DEVICE_SETTING_CONFIG)
+ assertThat(config.mainItems[0])
+ .isInstanceOf(DeviceSettingConfigItemModel.AppProvidedItem::class.java)
+ assertThat(config.mainItems[1])
+ .isInstanceOf(
+ DeviceSettingConfigItemModel.BuiltinItem.CommonBuiltinItem::class.java
+ )
+ assertThat(config.mainItems[2])
+ .isInstanceOf(
+ DeviceSettingConfigItemModel.BuiltinItem.BluetoothProfilesItem::class.java
+ )
}
}
@@ -163,16 +174,16 @@
fun getDeviceSettingsConfig_noMetadata_returnNull() {
testScope.runTest {
`when`(
- bluetoothDevice.getMetadata(
- DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
+ bluetoothDevice.getMetadata(
+ DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS
+ )
+ )
.thenReturn("".toByteArray())
`when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG)
- `when`(settingProviderService1.serviceStatus).thenReturn(
- DeviceSettingsProviderServiceStatus(true)
- )
- `when`(settingProviderService2.serviceStatus).thenReturn(
- DeviceSettingsProviderServiceStatus(true)
- )
+ `when`(settingProviderService1.serviceStatus)
+ .thenReturn(DeviceSettingsProviderServiceStatus(true))
+ `when`(settingProviderService2.serviceStatus)
+ .thenReturn(DeviceSettingsProviderServiceStatus(true))
val config = underTest.getDeviceSettingsConfig(cachedDevice)
@@ -184,12 +195,10 @@
fun getDeviceSettingsConfig_providerServiceNotEnabled_returnNull() {
testScope.runTest {
`when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG)
- `when`(settingProviderService1.serviceStatus).thenReturn(
- DeviceSettingsProviderServiceStatus(false)
- )
- `when`(settingProviderService2.serviceStatus).thenReturn(
- DeviceSettingsProviderServiceStatus(true)
- )
+ `when`(settingProviderService1.serviceStatus)
+ .thenReturn(DeviceSettingsProviderServiceStatus(false))
+ `when`(settingProviderService2.serviceStatus)
+ .thenReturn(DeviceSettingsProviderServiceStatus(true))
val config = underTest.getDeviceSettingsConfig(cachedDevice)
@@ -219,12 +228,10 @@
.getArgument<IDeviceSettingsListener>(1)
.onDeviceSettingsChanged(listOf(DEVICE_SETTING_1))
}
- `when`(settingProviderService1.serviceStatus).thenReturn(
- DeviceSettingsProviderServiceStatus(true)
- )
- `when`(settingProviderService2.serviceStatus).thenReturn(
- DeviceSettingsProviderServiceStatus(true)
- )
+ `when`(settingProviderService1.serviceStatus)
+ .thenReturn(DeviceSettingsProviderServiceStatus(true))
+ `when`(settingProviderService2.serviceStatus)
+ .thenReturn(DeviceSettingsProviderServiceStatus(true))
var setting: DeviceSettingModel? = null
underTest
@@ -247,12 +254,10 @@
.getArgument<IDeviceSettingsListener>(1)
.onDeviceSettingsChanged(listOf(DEVICE_SETTING_2))
}
- `when`(settingProviderService1.serviceStatus).thenReturn(
- DeviceSettingsProviderServiceStatus(true)
- )
- `when`(settingProviderService2.serviceStatus).thenReturn(
- DeviceSettingsProviderServiceStatus(true)
- )
+ `when`(settingProviderService1.serviceStatus)
+ .thenReturn(DeviceSettingsProviderServiceStatus(true))
+ `when`(settingProviderService2.serviceStatus)
+ .thenReturn(DeviceSettingsProviderServiceStatus(true))
var setting: DeviceSettingModel? = null
underTest
@@ -270,17 +275,15 @@
testScope.runTest {
`when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG)
`when`(settingProviderService2.registerDeviceSettingsListener(any(), any())).then {
- input ->
+ input ->
input
.getArgument<IDeviceSettingsListener>(1)
.onDeviceSettingsChanged(listOf(DEVICE_SETTING_HELP))
}
- `when`(settingProviderService1.serviceStatus).thenReturn(
- DeviceSettingsProviderServiceStatus(true)
- )
- `when`(settingProviderService2.serviceStatus).thenReturn(
- DeviceSettingsProviderServiceStatus(true)
- )
+ `when`(settingProviderService1.serviceStatus)
+ .thenReturn(DeviceSettingsProviderServiceStatus(true))
+ `when`(settingProviderService2.serviceStatus)
+ .thenReturn(DeviceSettingsProviderServiceStatus(true))
var setting: DeviceSettingModel? = null
underTest
@@ -324,12 +327,10 @@
.getArgument<IDeviceSettingsListener>(1)
.onDeviceSettingsChanged(listOf(DEVICE_SETTING_1))
}
- `when`(settingProviderService1.serviceStatus).thenReturn(
- DeviceSettingsProviderServiceStatus(true)
- )
- `when`(settingProviderService2.serviceStatus).thenReturn(
- DeviceSettingsProviderServiceStatus(true)
- )
+ `when`(settingProviderService1.serviceStatus)
+ .thenReturn(DeviceSettingsProviderServiceStatus(true))
+ `when`(settingProviderService2.serviceStatus)
+ .thenReturn(DeviceSettingsProviderServiceStatus(true))
var setting: DeviceSettingModel? = null
underTest
@@ -347,8 +348,10 @@
DeviceSettingState.Builder()
.setSettingId(DeviceSettingId.DEVICE_SETTING_ID_HEADER)
.setPreferenceState(
- ActionSwitchPreferenceState.Builder().setChecked(false).build())
- .build())
+ ActionSwitchPreferenceState.Builder().setChecked(false).build()
+ )
+ .build(),
+ )
}
}
@@ -362,12 +365,10 @@
.getArgument<IDeviceSettingsListener>(1)
.onDeviceSettingsChanged(listOf(DEVICE_SETTING_2))
}
- `when`(settingProviderService1.serviceStatus).thenReturn(
- DeviceSettingsProviderServiceStatus(true)
- )
- `when`(settingProviderService2.serviceStatus).thenReturn(
- DeviceSettingsProviderServiceStatus(true)
- )
+ `when`(settingProviderService1.serviceStatus)
+ .thenReturn(DeviceSettingsProviderServiceStatus(true))
+ `when`(settingProviderService2.serviceStatus)
+ .thenReturn(DeviceSettingsProviderServiceStatus(true))
var setting: DeviceSettingModel? = null
underTest
@@ -385,8 +386,10 @@
DeviceSettingState.Builder()
.setSettingId(DeviceSettingId.DEVICE_SETTING_ID_ANC)
.setPreferenceState(
- MultiTogglePreferenceState.Builder().setState(2).build())
- .build())
+ MultiTogglePreferenceState.Builder().setState(2).build()
+ )
+ .build(),
+ )
}
}
@@ -437,7 +440,7 @@
private fun assertConfig(
actual: DeviceSettingConfigModel,
- serviceResponse: DeviceSettingsConfig
+ serviceResponse: DeviceSettingsConfig,
) {
assertThat(actual.mainItems.size).isEqualTo(serviceResponse.mainContentItems.size)
for (i in 0..<actual.mainItems.size) {
@@ -451,7 +454,7 @@
private fun assertConfigItem(
actual: DeviceSettingConfigItemModel,
- serviceResponse: DeviceSettingItem
+ serviceResponse: DeviceSettingItem,
) {
assertThat(actual.settingId).isEqualTo(serviceResponse.settingId)
}
@@ -485,24 +488,43 @@
"</DEVICE_SETTINGS_CONFIG_ACTION>"
val DEVICE_INFO = DeviceInfo.Builder().setBluetoothAddress(BLUETOOTH_ADDRESS).build()
const val DEVICE_SETTING_ID_HELP = 12345
- val DEVICE_SETTING_ITEM_1 =
+ val DEVICE_SETTING_APP_PROVIDED_ITEM_1 =
DeviceSettingItem(
DeviceSettingId.DEVICE_SETTING_ID_HEADER,
SETTING_PROVIDER_SERVICE_PACKAGE_NAME_1,
SETTING_PROVIDER_SERVICE_CLASS_NAME_1,
- SETTING_PROVIDER_SERVICE_INTENT_ACTION_1)
- val DEVICE_SETTING_ITEM_2 =
+ SETTING_PROVIDER_SERVICE_INTENT_ACTION_1,
+ )
+ val DEVICE_SETTING_APP_PROVIDED_ITEM_2 =
DeviceSettingItem(
DeviceSettingId.DEVICE_SETTING_ID_ANC,
SETTING_PROVIDER_SERVICE_PACKAGE_NAME_2,
SETTING_PROVIDER_SERVICE_CLASS_NAME_2,
- SETTING_PROVIDER_SERVICE_INTENT_ACTION_2)
+ SETTING_PROVIDER_SERVICE_INTENT_ACTION_2,
+ )
+ val DEVICE_SETTING_BUILT_IN_ITEM =
+ DeviceSettingItem(
+ DeviceSettingId.DEVICE_SETTING_ID_BLUETOOTH_AUDIO_DEVICE_TYPE_GROUP,
+ "",
+ "",
+ "",
+ "device_type",
+ )
+ val DEVICE_SETTING_BUILT_IN_BT_PROFILES_ITEM =
+ DeviceSettingItem(
+ DeviceSettingId.DEVICE_SETTING_ID_BLUETOOTH_PROFILES,
+ "",
+ "",
+ "",
+ "bluetooth_profiles",
+ )
val DEVICE_SETTING_HELP_ITEM =
DeviceSettingItem(
DEVICE_SETTING_ID_HELP,
SETTING_PROVIDER_SERVICE_PACKAGE_NAME_2,
SETTING_PROVIDER_SERVICE_CLASS_NAME_2,
- SETTING_PROVIDER_SERVICE_INTENT_ACTION_2)
+ SETTING_PROVIDER_SERVICE_INTENT_ACTION_2,
+ )
val DEVICE_SETTING_1 =
DeviceSetting.Builder()
.setSettingId(DeviceSettingId.DEVICE_SETTING_ID_HEADER)
@@ -511,7 +533,8 @@
.setTitle("title1")
.setHasSwitch(true)
.setAllowedChangingState(true)
- .build())
+ .build()
+ )
.build()
val DEVICE_SETTING_2 =
DeviceSetting.Builder()
@@ -524,22 +547,30 @@
ToggleInfo.Builder()
.setLabel("label1")
.setIcon(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888))
- .build())
+ .build()
+ )
.addToggleInfo(
ToggleInfo.Builder()
.setLabel("label2")
.setIcon(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888))
- .build())
- .build())
+ .build()
+ )
+ .build()
+ )
.build()
- val DEVICE_SETTING_HELP = DeviceSetting.Builder()
- .setSettingId(DEVICE_SETTING_ID_HELP)
- .setPreference(DeviceSettingHelpPreference.Builder().setIntent(Intent()).build())
- .build()
+ val DEVICE_SETTING_HELP =
+ DeviceSetting.Builder()
+ .setSettingId(DEVICE_SETTING_ID_HELP)
+ .setPreference(DeviceSettingHelpPreference.Builder().setIntent(Intent()).build())
+ .build()
val DEVICE_SETTING_CONFIG =
DeviceSettingsConfig(
- listOf(DEVICE_SETTING_ITEM_1),
- listOf(DEVICE_SETTING_ITEM_2),
+ listOf(
+ DEVICE_SETTING_APP_PROVIDED_ITEM_1,
+ DEVICE_SETTING_BUILT_IN_ITEM,
+ DEVICE_SETTING_BUILT_IN_BT_PROFILES_ITEM,
+ ),
+ listOf(DEVICE_SETTING_APP_PROVIDED_ITEM_2),
DEVICE_SETTING_HELP_ITEM,
)
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
index a30613d..d08d91d 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
@@ -213,7 +213,7 @@
ZenMode zenMode = new ZenMode("id", azr, zenConfigRuleFor(azr, false));
assertThat(zenMode.getPolicy()).isEqualTo(
- new ZenPolicy.Builder()
+ new ZenPolicy.Builder(ZenModeConfig.getDefaultZenPolicy())
.disallowAllSounds()
.allowAlarms(true)
.allowMedia(true)
@@ -230,9 +230,8 @@
ZenMode zenMode = new ZenMode("id", azr, zenConfigRuleFor(azr, false));
assertThat(zenMode.getPolicy()).isEqualTo(
- new ZenPolicy.Builder()
+ new ZenPolicy.Builder(ZenModeConfig.getDefaultZenPolicy())
.disallowAllSounds()
- .hideAllVisualEffects()
.allowPriorityChannels(false)
.build());
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModesBackendTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModesBackendTest.java
index ff028dd..aae72b3 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModesBackendTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModesBackendTest.java
@@ -238,9 +238,16 @@
assertThat(mode.isManualDnd()).isTrue();
assertThat(mode.isEnabled()).isTrue();
assertThat(mode.isActive()).isTrue();
+
// Mode itself has a special fixed policy, different to the rule.
assertThat(mode.canEditPolicy()).isFalse();
- assertThat(mode.getPolicy()).isEqualTo(ZenMode.POLICY_INTERRUPTION_FILTER_ALARMS);
+ assertThat(mode.getPolicy()).isEqualTo(
+ new ZenPolicy.Builder(ZenModeConfig.getDefaultZenPolicy())
+ .disallowAllSounds()
+ .allowAlarms(true)
+ .allowMedia(true)
+ .allowPriorityChannels(false)
+ .build());
}
@Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
index ca53fc2..3f3e1b2 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java
@@ -291,4 +291,12 @@
assertThat(mPreference.isApplyDynamicColor()).isTrue();
}
+
+ @Test
+ public void setContentDescription_getContentDescription_isEqual() {
+ final String contentDesc = "content desc";
+ mPreference.setContentDescription(contentDesc);
+
+ assertThat(mPreference.getContentDescription().toString()).isEqualTo(contentDesc);
+ }
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index ec50323..e85ba45 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -2173,8 +2173,7 @@
(1 << AudioManager.STREAM_NOTIFICATION) |
(1 << AudioManager.STREAM_SYSTEM) |
(1 << AudioManager.STREAM_SYSTEM_ENFORCED);
- if (!mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_voice_capable)) {
+ if (!getTelephonyManager().isVoiceCapable()) {
ringerModeAffectedStreams |= (1 << AudioManager.STREAM_MUSIC);
}
loadSetting(stmt, Settings.System.MODE_RINGER_STREAMS_AFFECTED,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
index 121bd3e..bfbf41d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
@@ -99,6 +99,12 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.print("SyncDisabledForTests: ");
+ MyShellCommand.getSyncDisabledForTests(pw, pw);
+
+ pw.print("Is mainline: ");
+ pw.println(UpdatableDeviceConfigServiceReadiness.shouldStartUpdatableService());
+
final IContentProvider iprovider = mProvider.getIContentProvider();
pw.println("DeviceConfig flags:");
for (String line : MyShellCommand.listAll(iprovider)) {
@@ -232,6 +238,17 @@
return Binder.getCallingUid() == Process.ROOT_UID;
}
+ private static int getSyncDisabledForTests(PrintWriter pOut, PrintWriter pErr) {
+ int syncDisabledModeInt = DeviceConfig.getSyncDisabledMode();
+ String syncDisabledModeString = formatSyncDisabledMode(syncDisabledModeInt);
+ if (syncDisabledModeString == null) {
+ pErr.println("Unknown mode: " + syncDisabledModeInt);
+ return -1;
+ }
+ pOut.println(syncDisabledModeString);
+ return 0;
+ }
+
public static HashMap<String, String> getAllFlags(IContentProvider provider) {
HashMap<String, String> allFlags = new HashMap<String, String>();
for (DeviceConfig.Properties properties : DeviceConfig.getAllProperties()) {
@@ -597,14 +614,7 @@
DeviceConfig.setSyncDisabledMode(syncDisabledModeArg);
break;
case GET_SYNC_DISABLED_FOR_TESTS:
- int syncDisabledModeInt = DeviceConfig.getSyncDisabledMode();
- String syncDisabledModeString = formatSyncDisabledMode(syncDisabledModeInt);
- if (syncDisabledModeString == null) {
- perr.println("Unknown mode: " + syncDisabledModeInt);
- return -1;
- }
- pout.println(syncDisabledModeString);
- break;
+ return getSyncDisabledForTests(pout, perr);
default:
perr.println("Unspecified command");
return -1;
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 0b5187c..f3c5a18 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -941,6 +941,13 @@
<!-- Permission required for CTS test - FileIntegrityManagerTest -->
<uses-permission android:name="android.permission.SETUP_FSVERITY" />
+ <!-- Permissions required for CTS test - AppFunctionManagerTest -->
+ <uses-permission android:name="android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED" />
+ <uses-permission android:name="android.permission.EXECUTE_APP_FUNCTIONS" />
+
+ <!-- Permission required for CTS test - CtsNfcTestCases -->
+ <uses-permission android:name="android.permission.NFC_SET_CONTROLLER_ALWAYS_ON" />
+
<application
android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index d26a906..a9e81c7 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -756,6 +756,7 @@
"notification_flags_lib",
"PlatformComposeCore",
"PlatformComposeSceneTransitionLayout",
+ "PlatformComposeSceneTransitionLayoutTestsUtils",
"androidx.compose.runtime_runtime",
"androidx.compose.material3_material3",
"androidx.compose.material_material-icons-extended",
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
index c60eb61..fb1f715 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
+++ b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
@@ -41,6 +41,7 @@
"SettingsLibDisplayUtils",
"SettingsLibSettingsTheme",
"com_android_a11y_menu_flags_lib",
+ "//frameworks/libs/systemui:view_capture",
],
optimize: {
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_assistant_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_assistant.xml
similarity index 89%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_assistant_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_assistant.xml
index 9c3417f..6408a12 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_assistant_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_assistant.xml
@@ -1,6 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
+ android:width="108dp"
+ android:height="108dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_down_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_down.xml
similarity index 92%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_down_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_down.xml
index a64a0d1..f13239c 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_down_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_down.xml
@@ -1,6 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
+ android:width="108dp"
+ android:height="108dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_up_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_up.xml
similarity index 95%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_up_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_up.xml
index 40423c7..a5d15f9 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_up_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_brightness_up.xml
@@ -15,8 +15,8 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
+ android:width="108dp"
+ android:height="108dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_lock_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_lock.xml
similarity index 90%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_lock_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_lock.xml
index a0f7b5d..2127632 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_lock_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_lock.xml
@@ -1,6 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
+ android:width="108dp"
+ android:height="108dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_notifications_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_notifications.xml
similarity index 90%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_notifications_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_notifications.xml
index 8757f22..62c8d1d 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_notifications_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_notifications.xml
@@ -1,6 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
+ android:width="108dp"
+ android:height="108dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_power_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_power.xml
similarity index 90%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_power_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_power.xml
index 049013a..ed11b44 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_power_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_power.xml
@@ -1,6 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
+ android:width="108dp"
+ android:height="108dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_quick_settings_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_quick_settings.xml
similarity index 97%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_quick_settings_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_quick_settings.xml
index 4f25e7d..2da63a6 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_quick_settings_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_quick_settings.xml
@@ -15,8 +15,8 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
+ android:width="108dp"
+ android:height="108dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_recent_apps_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_recent_apps.xml
similarity index 94%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_recent_apps_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_recent_apps.xml
index 38234c0..9763b8e 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_recent_apps_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_recent_apps.xml
@@ -15,8 +15,8 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
+ android:width="108dp"
+ android:height="108dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_screenshot_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_screenshot.xml
similarity index 95%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_screenshot_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_screenshot.xml
index 6d7f49c..2bfbd5b 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_screenshot_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_screenshot.xml
@@ -15,8 +15,8 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
+ android:width="108dp"
+ android:height="108dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_settings_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_settings.xml
similarity index 95%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_settings_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_settings.xml
index 5ed6f19..4ca9bfc 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_settings_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_settings.xml
@@ -15,8 +15,8 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
+ android:width="108dp"
+ android:height="108dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_down_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_down.xml
similarity index 94%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_down_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_down.xml
index 16653e8..f924e5e 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_down_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_down.xml
@@ -15,8 +15,8 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
+ android:width="108dp"
+ android:height="108dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_up_24dp.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_up.xml
similarity index 95%
rename from packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_up_24dp.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_up.xml
index e572c6a..41fe351 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_up_24dp.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/ic_logo_a11y_volume_up.xml
@@ -15,8 +15,8 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
+ android:width="108dp"
+ android:height="108dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="@color/colorControlNormal">
diff --git a/packages/SystemUI/res/color/brightness_slider_track.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/menuitem_background_ripple.xml
similarity index 79%
rename from packages/SystemUI/res/color/brightness_slider_track.xml
rename to packages/SystemUI/accessibility/accessibilitymenu/res/drawable/menuitem_background_ripple.xml
index 6028769..6cab464 100644
--- a/packages/SystemUI/res/color/brightness_slider_track.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/drawable/menuitem_background_ripple.xml
@@ -14,6 +14,5 @@
~ limitations under the License.
-->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="@android:color/system_neutral2_500" android:lStar="40" />
-</selector>
\ No newline at end of file
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="@color/ripple_material_color" />
\ No newline at end of file
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml
index fd9a9c6..a1130e6 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml
@@ -3,8 +3,7 @@
android:id="@+id/shortcutItem"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingTop="@dimen/grid_item_padding"
- android:paddingBottom="@dimen/grid_item_padding"
+ android:padding="@dimen/grid_item_padding"
android:gravity="center">
<ImageButton
@@ -13,7 +12,8 @@
android:layout_height="@dimen/image_button_height"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
- android:scaleType="fitCenter"/>
+ android:scaleType="fitCenter"
+ android:background="@drawable/menuitem_background_ripple" />
<TextView
android:id="@+id/shortcutLabel"
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml
index 6be7655..adaa655 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml
@@ -1,25 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
-<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/row_width"
android:layout_height="match_parent"
- android:id="@+id/coordinatorLayout"
- android:background="@drawable/view_background"
- >
- <LinearLayout
+ android:orientation="vertical"
+ android:background="@drawable/view_background">
+
+ <androidx.viewpager2.widget.ViewPager2
+ android:id="@+id/view_pager"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:paddingTop="@dimen/table_margin_top"
+ android:paddingBottom="@dimen/a11ymenu_layout_margin"
+ android:gravity="center"
+ />
- <androidx.viewpager2.widget.ViewPager2
- android:id="@+id/view_pager"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="@dimen/table_margin_top"
- android:paddingBottom="@dimen/a11ymenu_layout_margin"
- android:layout_gravity="center"
- android:gravity="center"
- />
-
- <include layout="@layout/footerlayout_switch_page"/>
- </LinearLayout>
-</androidx.coordinatorlayout.widget.CoordinatorLayout>
+ <include layout="@layout/footerlayout_switch_page"/>
+</LinearLayout>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java
index c698d18..11ce41e 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/model/A11yMenuShortcut.java
@@ -53,73 +53,73 @@
/** Map stores all shortcut resource IDs that is in matching order of defined shortcut. */
private static final Map<ShortcutId, int[]> sShortcutResource = Map.ofEntries(
Map.entry(ShortcutId.ID_ASSISTANT_VALUE, new int[] {
- R.drawable.ic_logo_a11y_assistant_24dp,
+ R.drawable.ic_logo_a11y_assistant,
R.color.assistant_color,
R.string.assistant_utterance,
R.string.assistant_label,
}),
Map.entry(ShortcutId.ID_A11YSETTING_VALUE, new int[] {
- R.drawable.ic_logo_a11y_settings_24dp,
+ R.drawable.ic_logo_a11y_settings,
R.color.a11y_settings_color,
R.string.a11y_settings_label,
R.string.a11y_settings_label,
}),
Map.entry(ShortcutId.ID_POWER_VALUE, new int[] {
- R.drawable.ic_logo_a11y_power_24dp,
+ R.drawable.ic_logo_a11y_power,
R.color.power_color,
R.string.power_utterance,
R.string.power_label,
}),
Map.entry(ShortcutId.ID_RECENT_VALUE, new int[] {
- R.drawable.ic_logo_a11y_recent_apps_24dp,
+ R.drawable.ic_logo_a11y_recent_apps,
R.color.recent_apps_color,
R.string.recent_apps_label,
R.string.recent_apps_label,
}),
Map.entry(ShortcutId.ID_LOCKSCREEN_VALUE, new int[] {
- R.drawable.ic_logo_a11y_lock_24dp,
+ R.drawable.ic_logo_a11y_lock,
R.color.lockscreen_color,
R.string.lockscreen_label,
R.string.lockscreen_label,
}),
Map.entry(ShortcutId.ID_QUICKSETTING_VALUE, new int[] {
- R.drawable.ic_logo_a11y_quick_settings_24dp,
+ R.drawable.ic_logo_a11y_quick_settings,
R.color.quick_settings_color,
R.string.quick_settings_label,
R.string.quick_settings_label,
}),
Map.entry(ShortcutId.ID_NOTIFICATION_VALUE, new int[] {
- R.drawable.ic_logo_a11y_notifications_24dp,
+ R.drawable.ic_logo_a11y_notifications,
R.color.notifications_color,
R.string.notifications_label,
R.string.notifications_label,
}),
Map.entry(ShortcutId.ID_SCREENSHOT_VALUE, new int[] {
- R.drawable.ic_logo_a11y_screenshot_24dp,
+ R.drawable.ic_logo_a11y_screenshot,
R.color.screenshot_color,
R.string.screenshot_utterance,
R.string.screenshot_label,
}),
Map.entry(ShortcutId.ID_BRIGHTNESS_UP_VALUE, new int[] {
- R.drawable.ic_logo_a11y_brightness_up_24dp,
+ R.drawable.ic_logo_a11y_brightness_up,
R.color.brightness_color,
R.string.brightness_up_label,
R.string.brightness_up_label,
}),
Map.entry(ShortcutId.ID_BRIGHTNESS_DOWN_VALUE, new int[] {
- R.drawable.ic_logo_a11y_brightness_down_24dp,
+ R.drawable.ic_logo_a11y_brightness_down,
R.color.brightness_color,
R.string.brightness_down_label,
R.string.brightness_down_label,
}),
Map.entry(ShortcutId.ID_VOLUME_UP_VALUE, new int[] {
- R.drawable.ic_logo_a11y_volume_up_24dp,
+ R.drawable.ic_logo_a11y_volume_up,
R.color.volume_color,
R.string.volume_up_label,
R.string.volume_up_label,
}),
Map.entry(ShortcutId.ID_VOLUME_DOWN_VALUE, new int[] {
- R.drawable.ic_logo_a11y_volume_down_24dp,
+ R.drawable.ic_logo_a11y_volume_down,
R.color.volume_color,
R.string.volume_down_label,
R.string.volume_down_label,
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/utils/ShortcutDrawableUtils.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/utils/ShortcutDrawableUtils.java
deleted file mode 100644
index 28ba4b5..0000000
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/utils/ShortcutDrawableUtils.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2022 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.accessibility.accessibilitymenu.utils;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
-import android.graphics.drawable.AdaptiveIconDrawable;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.graphics.drawable.RippleDrawable;
-
-import com.android.systemui.accessibility.accessibilitymenu.R;
-
-/** Creates background drawable for a11y menu shortcut. */
-public class ShortcutDrawableUtils {
-
- /**
- * To make the circular background of shortcut icons have higher resolution. The higher value of
- * LENGTH is, the higher resolution of the circular background are.
- */
- private static final int LENGTH = 480;
-
- private static final int RADIUS = LENGTH / 2;
- private static final int COORDINATE = LENGTH / 2;
- private static final int RIPPLE_COLOR_ID = R.color.ripple_material_color;
-
- private final Context mContext;
- private final ColorStateList mRippleColorStateList;
-
- // Placeholder of drawable to prevent NullPointerException
- private final ColorDrawable mTransparentDrawable = new ColorDrawable(Color.TRANSPARENT);
-
- public ShortcutDrawableUtils(Context context) {
- this.mContext = context;
-
- int rippleColor = context.getColor(RIPPLE_COLOR_ID);
- mRippleColorStateList = ColorStateList.valueOf(rippleColor);
- }
-
- /**
- * Creates a circular drawable in specific color for shortcut.
- *
- * @param colorResId color resource ID
- * @return drawable circular drawable
- */
- public Drawable createCircularDrawable(int colorResId) {
- Bitmap output = Bitmap.createBitmap(LENGTH, LENGTH, Config.ARGB_8888);
- Canvas canvas = new Canvas(output);
- int color = mContext.getColor(colorResId);
- Paint paint = new Paint();
- paint.setColor(color);
- paint.setStrokeCap(Paint.Cap.ROUND);
- paint.setStyle(Style.FILL);
- canvas.drawCircle(COORDINATE, COORDINATE, RADIUS, paint);
-
- BitmapDrawable drawable = new BitmapDrawable(mContext.getResources(), output);
- return drawable;
- }
-
- /**
- * Creates an adaptive icon drawable in specific color for shortcut.
- *
- * @param colorResId color resource ID
- * @return drawable for adaptive icon
- */
- public Drawable createAdaptiveIconDrawable(int colorResId) {
- Drawable circleLayer = createCircularDrawable(colorResId);
- RippleDrawable rippleLayer = new RippleDrawable(mRippleColorStateList, null, null);
-
- AdaptiveIconDrawable adaptiveIconDrawable =
- new AdaptiveIconDrawable(circleLayer, mTransparentDrawable);
-
- Drawable[] layers = {adaptiveIconDrawable, rippleLayer};
- LayerDrawable drawable = new LayerDrawable(layers);
- return drawable;
- }
-}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java
index c333a7a..aa1bbbd 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuAdapter.java
@@ -16,7 +16,12 @@
package com.android.systemui.accessibility.accessibilitymenu.view;
+import android.content.res.Resources;
import android.graphics.Rect;
+import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.InsetDrawable;
import android.view.LayoutInflater;
import android.view.TouchDelegate;
import android.view.View;
@@ -26,11 +31,12 @@
import android.widget.ImageButton;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+
import com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService;
import com.android.systemui.accessibility.accessibilitymenu.R;
import com.android.systemui.accessibility.accessibilitymenu.activity.A11yMenuSettingsActivity.A11yMenuPreferenceFragment;
import com.android.systemui.accessibility.accessibilitymenu.model.A11yMenuShortcut;
-import com.android.systemui.accessibility.accessibilitymenu.utils.ShortcutDrawableUtils;
import java.util.List;
@@ -43,16 +49,12 @@
private final AccessibilityMenuService mService;
private final List<A11yMenuShortcut> mShortcutDataList;
- private final ShortcutDrawableUtils mShortcutDrawableUtils;
public A11yMenuAdapter(
AccessibilityMenuService service,
List<A11yMenuShortcut> shortcutDataList) {
this.mService = service;
this.mShortcutDataList = shortcutDataList;
-
- mShortcutDrawableUtils = new ShortcutDrawableUtils(service);
-
mLargeTextSize =
service.getResources().getDimensionPixelOffset(R.dimen.large_label_text_size);
}
@@ -152,10 +154,10 @@
shortcutIconButton.setContentDescription(
mService.getString(shortcutItem.imgContentDescription));
shortcutLabel.setText(shortcutItem.labelText);
- shortcutIconButton.setImageResource(shortcutItem.imageSrc);
- shortcutIconButton.setBackground(
- mShortcutDrawableUtils.createAdaptiveIconDrawable(shortcutItem.imageColor));
+ AdaptiveIconDrawable iconDrawable = getAdaptiveIconDrawable(convertView,
+ shortcutItem);
+ shortcutIconButton.setImageDrawable(iconDrawable);
shortcutIconButton.setAccessibilityDelegate(new View.AccessibilityDelegate() {
@Override
@@ -167,4 +169,18 @@
});
}
}
+
+ @NonNull
+ private static AdaptiveIconDrawable getAdaptiveIconDrawable(@NonNull View convertView,
+ @NonNull A11yMenuShortcut shortcutItem) {
+ Resources resources = convertView.getResources();
+ // Note: from the official guide, the foreground image of the adaptive icon should be
+ // sized at 108 x 108 dp
+ Drawable icon = resources.getDrawable(shortcutItem.imageSrc);
+ float inset = AdaptiveIconDrawable.getExtraInsetFraction();
+ AdaptiveIconDrawable iconDrawable = new AdaptiveIconDrawable(
+ new ColorDrawable(resources.getColor(shortcutItem.imageColor)),
+ new InsetDrawable(icon, inset));
+ return iconDrawable;
+ }
}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java
index 78fbf01..136a4ed 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java
@@ -55,6 +55,8 @@
private View mBottomListDivider;
private final A11yMenuFooterCallBack mCallBack;
private final ViewGroup mMenuLayout;
+ private ViewGroup mFooterContainer;
+ private int mFooterContainerBaseHeight = 0;
private int mRightToLeftDirection = LAYOUT_DIRECTION_LTR;
public A11yMenuFooter(ViewGroup menuLayout, A11yMenuFooterCallBack callBack) {
@@ -74,6 +76,15 @@
? mPageRightBtn : mPageLeftBtn;
}
+ void adjustFooterToDensityScale(float densityScale) {
+ mFooterContainer.getLayoutParams().height =
+ (int) (mFooterContainerBaseHeight / densityScale);
+ }
+
+ int getHeight() {
+ return mFooterContainer.getLayoutParams().height;
+ }
+
/** Sets right to left direction of footer. */
public void updateRightToLeftDirection(Configuration configuration) {
mRightToLeftDirection = TextUtils.getLayoutDirectionFromLocale(
@@ -85,8 +96,9 @@
}
private void configureFooterLayout(ViewGroup menuLayout) {
- ViewGroup footerContainer = menuLayout.findViewById(R.id.footerlayout);
- footerContainer.setVisibility(View.VISIBLE);
+ mFooterContainer = menuLayout.findViewById(R.id.footerlayout);
+ mFooterContainer.setVisibility(View.VISIBLE);
+ mFooterContainerBaseHeight = mFooterContainer.getLayoutParams().height;
mPageLeftBtn = menuLayout.findViewById(R.id.menu_left_button);
mPageRightBtn = menuLayout.findViewById(R.id.menu_right_button);
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
index 448472d..3db61a5 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
@@ -22,6 +22,8 @@
import static android.view.View.ACCESSIBILITY_LIVE_REGION_POLITE;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
+import static com.android.app.viewcapture.ViewCaptureFactory.getViewCaptureAwareWindowManagerInstance;
+
import static java.lang.Math.max;
import android.animation.Animator;
@@ -53,6 +55,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.UiContext;
+import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
import com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService;
import com.android.systemui.accessibility.accessibilitymenu.Flags;
import com.android.systemui.accessibility.accessibilitymenu.R;
@@ -143,7 +146,9 @@
final Display display = mDisplayManager.getDisplay(DEFAULT_DISPLAY);
final Context uiContext = mService.createWindowContext(
display, TYPE_ACCESSIBILITY_OVERLAY, /* options= */null);
- final WindowManager windowManager = uiContext.getSystemService(WindowManager.class);
+ final ViewCaptureAwareWindowManager windowManager =
+ getViewCaptureAwareWindowManagerInstance(uiContext,
+ com.android.systemui.Flags.enableViewCaptureTracing());
mLayout = new A11yMenuFrameLayout(uiContext);
updateLayoutPosition(uiContext);
inflateLayoutAndSetOnTouchListener(mLayout, uiContext);
@@ -158,8 +163,8 @@
public void clearLayout() {
if (mLayout != null) {
- WindowManager windowManager =
- mLayout.getContext().getSystemService(WindowManager.class);
+ ViewCaptureAwareWindowManager windowManager = getViewCaptureAwareWindowManagerInstance(
+ mLayout.getContext(), com.android.systemui.Flags.enableViewCaptureTracing());
if (windowManager != null) {
windowManager.removeView(mLayout);
}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
index a29ce82..b899c45 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
@@ -28,6 +28,7 @@
import android.view.WindowMetrics;
import android.widget.GridView;
+import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;
import com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService;
@@ -163,7 +164,9 @@
mA11yMenuShortcutList = shortcutDataList;
initViewPager();
initChildPage();
- mA11yMenuFooter = new A11yMenuFooter(a11yMenuLayout, mFooterCallbacks);
+ if (mA11yMenuFooter == null) {
+ mA11yMenuFooter = new A11yMenuFooter(a11yMenuLayout, mFooterCallbacks);
+ }
mA11yMenuFooter.updateRightToLeftDirection(
a11yMenuLayout.getResources().getConfiguration());
updateFooterState();
@@ -233,11 +236,17 @@
return;
}
- if (mGridPageList.isEmpty()) {
+ if (mViewPagerAdapter.getItemCount() == 0) {
return;
}
- GridView firstGridView = mGridPageList.get(0);
+ RecyclerView.ViewHolder viewHolder =
+ ((RecyclerView) mViewPager.getChildAt(0))
+ .findViewHolderForAdapterPosition(0);
+ if (viewHolder == null) {
+ return;
+ }
+ GridView firstGridView = (GridView) viewHolder.itemView;
if (firstGridView == null
|| firstGridView.getChildAt(0) == null) {
return;
@@ -280,10 +289,8 @@
DisplayMetrics displayMetrics = mService.getResources().getDisplayMetrics();
float densityScale = (float) displayMetrics.densityDpi
/ DisplayMetrics.DENSITY_DEVICE_STABLE;
- View footerLayout = mA11yMenuLayout.findViewById(R.id.footerlayout);
// Keeps footer window height unchanged no matter the density is changed.
- footerLayout.getLayoutParams().height =
- (int) (footerLayout.getLayoutParams().height / densityScale);
+ mA11yMenuFooter.adjustFooterToDensityScale(densityScale);
// Adjust the view pager height for system bar and display cutout insets.
WindowManager windowManager = mA11yMenuLayout.getContext()
.getSystemService(WindowManager.class);
@@ -292,20 +299,22 @@
WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
viewPagerHeight =
windowMetric.getBounds().height()
- - footerLayout.getLayoutParams().height
+ - mA11yMenuFooter.getHeight()
- windowInsets.bottom;
// Sets vertical interval between grid items.
int interval =
(viewPagerHeight - topMargin - defaultMargin
- (rowsInGridView * gridItemHeight))
/ (rowsInGridView + 1);
- for (GridView gridView : mGridPageList) {
- gridView.setVerticalSpacing(interval);
- }
+ // The interval is negative number when the viewPagerHeight is not able to fit
+ // the grid items, which result in text overlapping.
+ // Adjust the interval to 0 could solve the issue.
+ interval = Math.max(interval, 0);
+ mViewPagerAdapter.setVerticalSpacing(interval);
// Sets padding to view pager.
final int finalMarginTop = interval + topMargin;
- mViewPager.setPadding(defaultMargin, finalMarginTop, defaultMargin, defaultMargin);
+ mViewPager.setPadding(0, finalMarginTop, 0, defaultMargin);
}
final ViewGroup.LayoutParams layoutParams = mViewPager.getLayoutParams();
layoutParams.height = viewPagerHeight;
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java
index 152ff68..4b14e51 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java
@@ -36,11 +36,19 @@
/** List of shortcuts, split into sub lists per page */
private List<List<A11yMenuShortcut>> mShortcutList;
private final AccessibilityMenuService mService;
+ private int mVerticalSpacing = 0;
ViewPagerAdapter(AccessibilityMenuService service) {
mService = service;
}
+ public void setVerticalSpacing(int spacing) {
+ if (mVerticalSpacing != spacing) {
+ mVerticalSpacing = spacing;
+ notifyDataSetChanged();
+ }
+ }
+
public void set(List<List<A11yMenuShortcut>> tList) {
mShortcutList = tList;
notifyDataSetChanged();
@@ -61,6 +69,7 @@
GridView gridView = (GridView) holder.itemView;
gridView.setNumColumns(A11yMenuViewPager.GridViewParams.getGridColumnCount(mService));
gridView.setAdapter(adapter);
+ gridView.setVerticalSpacing(mVerticalSpacing);
}
@Override
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index cf13621..7c89592 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -288,6 +288,16 @@
}
flag {
+ name: "qs_quick_rebind_active_tiles"
+ namespace: "systemui"
+ description: "Rebind active custom tiles quickly."
+ bug: "362526228"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "coroutine_tracing"
namespace: "systemui"
description: "Adds thread-local data to System UI's global coroutine scopes to "
@@ -637,10 +647,13 @@
}
flag {
- name: "smartspace_remoteviews_rendering"
+ name: "smartspace_remoteviews_rendering_fix"
namespace: "systemui"
description: "Indicate Smartspace RemoteViews rendering"
bug: "326292691"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
flag {
@@ -651,6 +664,13 @@
}
flag {
+ name: "smartspace_viewpager2"
+ namespace: "systemui"
+ description: "Use viewpager2 in Smartspace"
+ bug: "259566300"
+}
+
+flag {
name: "pin_input_field_styled_focus_state"
namespace: "systemui"
description: "Enables styled focus states on pin input field if keyboard is connected"
@@ -1330,15 +1350,6 @@
}
flag {
- name: "lockscreen_preview_renderer_create_on_main_thread"
- namespace: "systemui"
- description: "Force preview renderer to be created on the main thread"
- bug: "343732179"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-flag {
name: "classic_flags_multi_user"
namespace: "systemui"
description: "Make the classic feature flag loading multi user aware."
@@ -1395,3 +1406,9 @@
}
}
+flag {
+ name: "non_touchscreen_devices_bypass_falsing"
+ namespace: "systemui"
+ description: "Allow non-touchscreen devices to bypass falsing"
+ bug: "319809270"
+}
\ No newline at end of file
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt
index 9f78d69..34eafde 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt
@@ -102,6 +102,7 @@
import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel
import com.android.systemui.common.shared.model.Text.Companion.loadText
import com.android.systemui.common.ui.compose.Icon
+import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.fold.ui.composable.foldPosture
import com.android.systemui.fold.ui.helper.FoldPosture
import com.android.systemui.res.R
@@ -259,8 +260,11 @@
viewModel = viewModel.message,
modifier = Modifier.align(Alignment.TopCenter),
)
-
- OutputArea(viewModel = viewModel, modifier = Modifier.align(Alignment.Center))
+ OutputArea(
+ viewModel = viewModel,
+ modifier =
+ Modifier.align(Alignment.Center).sysuiResTag("bouncer_text_entry")
+ )
ActionArea(
viewModel = viewModel,
@@ -310,8 +314,11 @@
StatusMessage(
viewModel = viewModel.message,
)
-
- OutputArea(viewModel = viewModel, modifier = Modifier.padding(top = 24.dp))
+ OutputArea(
+ viewModel = viewModel,
+ modifier =
+ Modifier.padding(top = 24.dp).sysuiResTag("bouncer_text_entry")
+ )
}
}
else -> Unit
@@ -417,10 +424,9 @@
StatusMessage(
viewModel = viewModel.message,
)
-
OutputArea(
viewModel = viewModel,
- modifier = Modifier.padding(top = 24.dp).testTag("OutputArea")
+ modifier = Modifier.padding(top = 24.dp).sysuiResTag("bouncer_text_entry")
)
}
},
@@ -485,7 +491,6 @@
StatusMessage(
viewModel = viewModel.message,
)
-
OutputArea(viewModel = viewModel, modifier = Modifier.padding(top = 24.dp))
InputArea(
@@ -654,17 +659,16 @@
) {
val authMethodViewModel: AuthMethodBouncerViewModel? by
viewModel.authMethodViewModel.collectAsStateWithLifecycle()
-
when (val nonNullViewModel = authMethodViewModel) {
is PinBouncerViewModel ->
PinInputDisplay(
viewModel = nonNullViewModel,
- modifier = modifier,
+ modifier = modifier.sysuiResTag("bouncer_text_entry")
)
is PasswordBouncerViewModel ->
PasswordBouncer(
viewModel = nonNullViewModel,
- modifier = modifier,
+ modifier = modifier.sysuiResTag("bouncer_text_entry")
)
else -> Unit
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
index c5bb33c..ae92d259 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
@@ -27,8 +27,8 @@
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.bouncer.ui.BouncerDialogFactory
-import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneActionsViewModel
import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel
+import com.android.systemui.bouncer.ui.viewmodel.BouncerUserActionsViewModel
import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.ExclusiveActivatable
@@ -54,18 +54,17 @@
class BouncerScene
@Inject
constructor(
- private val actionsViewModelFactory: BouncerSceneActionsViewModel.Factory,
+ private val actionsViewModelFactory: BouncerUserActionsViewModel.Factory,
private val contentViewModelFactory: BouncerSceneContentViewModel.Factory,
private val dialogFactory: BouncerDialogFactory,
) : ExclusiveActivatable(), Scene {
override val key = Scenes.Bouncer
- private val actionsViewModel: BouncerSceneActionsViewModel by lazy {
+ private val actionsViewModel: BouncerUserActionsViewModel by lazy {
actionsViewModelFactory.create()
}
- override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
- actionsViewModel.actions
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
override suspend fun onActivated(): Nothing {
actionsViewModel.activate()
@@ -100,8 +99,8 @@
BouncerContent(
viewModel,
dialogFactory,
- Modifier.sysuiResTag(Bouncer.TestTags.Root)
- .element(Bouncer.Elements.Content)
+ Modifier.element(Bouncer.Elements.Content)
+ .sysuiResTag(Bouncer.TestTags.Root)
.fillMaxSize()
)
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt
index 4ec0d99..480e4e4 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt
@@ -93,11 +93,15 @@
}
}
+ // set the focus, so adb can send the key events for testing.
+ val focusRequester = FocusRequester()
+ LaunchedEffect(Unit) { focusRequester.requestFocus() }
+
VerticalGrid(
columns = columns,
verticalSpacing = verticalSpacing,
horizontalSpacing = calculateHorizontalSpacingBetweenColumns(gridWidth = 300.dp),
- modifier = modifier,
+ modifier = modifier.focusRequester(focusRequester)
) {
repeat(9) { index ->
DigitButton(
@@ -285,26 +289,26 @@
Box(
contentAlignment = Alignment.Center,
modifier =
- modifier
- .focusRequester(FocusRequester.Default)
- .focusable()
- .sizeIn(maxWidth = pinButtonMaxSize, maxHeight = pinButtonMaxSize)
- .aspectRatio(1f)
- .drawBehind {
- drawRoundRect(
- color = containerColor,
- cornerRadius = CornerRadius(cornerRadius.toPx()),
- )
- }
- .clip(CircleShape)
- .thenIf(isEnabled) {
- Modifier.combinedClickable(
- interactionSource = interactionSource,
- indication = indication,
- onClick = onClicked,
- onLongClick = onLongPressed
- )
- },
+ modifier
+ .focusRequester(FocusRequester.Default)
+ .focusable()
+ .sizeIn(maxWidth = pinButtonMaxSize, maxHeight = pinButtonMaxSize)
+ .aspectRatio(1f)
+ .drawBehind {
+ drawRoundRect(
+ color = containerColor,
+ cornerRadius = CornerRadius(cornerRadius.toPx()),
+ )
+ }
+ .clip(CircleShape)
+ .thenIf(isEnabled) {
+ Modifier.combinedClickable(
+ interactionSource = interactionSource,
+ indication = indication,
+ onClick = onClicked,
+ onLongClick = onLongPressed
+ )
+ },
) {
content(contentColor::value)
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinInputDisplay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinInputDisplay.kt
index 465eade..ba885f7 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinInputDisplay.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinInputDisplay.kt
@@ -34,8 +34,10 @@
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
@@ -351,14 +353,17 @@
@Composable
fun Content(modifier: Modifier) {
- Row(
- modifier =
+
+ // Wrap PIN entry in a Box so it is visible to accessibility (even if empty).
+ Box(modifier = modifier.fillMaxWidth().wrapContentHeight()) {
+ Row(
modifier
.heightIn(min = shapeAnimations.shapeSize)
// Pins overflowing horizontally should still be shown as scrolling.
- .wrapContentSize(unbounded = true),
- ) {
- entries.forEach { entry -> key(entry.digit) { entry.Content() } }
+ .wrapContentSize(unbounded = true)
+ ) {
+ entries.forEach { entry -> key(entry.digit) { entry.Content() } }
+ }
}
}
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 ed12776..a4dc8fc 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
@@ -216,7 +216,7 @@
/** Scene containing the glanceable hub UI. */
@Composable
-private fun SceneScope.CommunalScene(
+fun SceneScope.CommunalScene(
backgroundType: CommunalBackgroundType,
colors: CommunalColors,
content: CommunalContent,
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index be6a0f9..c63b29d 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -65,6 +65,7 @@
import androidx.compose.foundation.lazy.grid.GridItemSpan
import androidx.compose.foundation.lazy.grid.LazyGridState
import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid
+import androidx.compose.foundation.lazy.grid.itemsIndexed
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.selection.selectable
@@ -136,6 +137,7 @@
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.customActions
import androidx.compose.ui.semantics.onClick
+import androidx.compose.ui.semantics.paneTitle
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.text.style.TextAlign
@@ -196,7 +198,12 @@
val gridState =
rememberLazyGridState(viewModel.savedFirstScrollIndex, viewModel.savedFirstScrollOffset)
- viewModel.clearPersistedScrollPosition()
+
+ LaunchedEffect(Unit) {
+ if (!viewModel.isEditMode) {
+ viewModel.clearPersistedScrollPosition()
+ }
+ }
val contentListState = rememberContentListState(widgetConfigurator, communalContent, viewModel)
val reorderingWidgets by viewModel.reorderingWidgets.collectAsStateWithLifecycle()
@@ -219,7 +226,6 @@
val windowMetrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context)
val screenWidth = windowMetrics.bounds.width()
val layoutDirection = LocalLayoutDirection.current
-
if (viewModel.isEditMode) {
ObserveNewWidgetAddedEffect(communalContent, gridState, viewModel)
} else {
@@ -236,10 +242,15 @@
}
}
+ val paneTitle = stringResource(R.string.accessibility_content_description_for_communal_hub)
+
Box(
modifier =
modifier
- .semantics { testTagsAsResourceId = true }
+ .semantics {
+ testTagsAsResourceId = true
+ this.paneTitle = paneTitle
+ }
.testTag(COMMUNAL_HUB_TEST_TAG)
.fillMaxSize()
// Observe taps for selecting items
@@ -543,7 +554,6 @@
communalContent: List<CommunalContentModel>,
gridState: LazyGridState,
) {
- val coroutineScope = rememberCoroutineScope()
val liveContentKeys = remember { mutableListOf<String>() }
var communalContentPending by remember { mutableStateOf(true) }
@@ -687,21 +697,20 @@
horizontalArrangement = Arrangement.spacedBy(Dimensions.ItemSpacing),
verticalArrangement = Arrangement.spacedBy(Dimensions.ItemSpacing),
) {
- items(
- count = list.size,
- key = { index -> list[index].key },
- contentType = { index -> list[index].key },
- span = { index -> GridItemSpan(list[index].size.span) },
- ) { index ->
+ itemsIndexed(
+ items = list,
+ key = { _, item -> item.key },
+ contentType = { _, item -> item.key },
+ span = { _, item -> GridItemSpan(item.size.span) },
+ ) { index, item ->
val size =
SizeF(
Dimensions.CardWidth.value,
- list[index].size.dp().value,
+ item.size.dp().value,
)
val cardModifier = Modifier.requiredSize(width = size.width.dp, height = size.height.dp)
if (viewModel.isEditMode && dragDropState != null) {
- val selected by
- remember(index) { derivedStateOf { list[index].key == selectedKey.value } }
+ val selected = item.key == selectedKey.value
DraggableItem(
modifier =
if (dragDropState.draggingItemIndex == index) {
@@ -713,12 +722,12 @@
},
dragDropState = dragDropState,
selected = selected,
- enabled = list[index].isWidgetContent(),
+ enabled = item.isWidgetContent(),
index = index,
) { isDragging ->
CommunalContent(
modifier = cardModifier,
- model = list[index],
+ model = item,
viewModel = viewModel,
size = size,
selected = selected && !isDragging,
@@ -731,7 +740,7 @@
}
} else {
CommunalContent(
- model = list[index],
+ model = item,
viewModel = viewModel,
size = size,
selected = false,
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt
index f658169..e41a7df 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt
@@ -17,20 +17,21 @@
package com.android.systemui.communal.ui.compose
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.scene.SceneScope
import com.android.compose.animation.scene.Swipe
import com.android.compose.animation.scene.SwipeDirection
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
-import com.android.systemui.communal.ui.view.layout.sections.CommunalAppWidgetSection
+import com.android.systemui.communal.shared.model.CommunalBackgroundType
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
-import com.android.systemui.communal.widgets.WidgetInteractionHandler
+import com.android.systemui.communal.util.CommunalColors
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.composable.Scene
-import com.android.systemui.statusbar.phone.SystemUIDialogFactory
import javax.inject.Inject
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.Flow
@@ -43,16 +44,15 @@
@Inject
constructor(
private val viewModel: CommunalViewModel,
- private val dialogFactory: SystemUIDialogFactory,
- private val interactionHandler: WidgetInteractionHandler,
- private val widgetSection: CommunalAppWidgetSection,
+ private val communalColors: CommunalColors,
+ private val communalContent: CommunalContent,
) : ExclusiveActivatable(), Scene {
override val key = Scenes.Communal
- override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
- MutableStateFlow<Map<UserAction, UserActionResult>>(
+ override val userActions: Flow<Map<UserAction, UserActionResult>> =
+ MutableStateFlow(
mapOf(
- Swipe(SwipeDirection.End) to UserActionResult(Scenes.Lockscreen),
+ Swipe(SwipeDirection.End) to Scenes.Lockscreen,
)
)
.asStateFlow()
@@ -63,12 +63,17 @@
@Composable
override fun SceneScope.Content(modifier: Modifier) {
- CommunalHub(
- modifier = modifier,
+ val backgroundType by
+ viewModel.communalBackground.collectAsStateWithLifecycle(
+ initialValue = CommunalBackgroundType.ANIMATED
+ )
+
+ CommunalScene(
+ backgroundType = backgroundType,
+ colors = communalColors,
+ content = communalContent,
viewModel = viewModel,
- interactionHandler = interactionHandler,
- widgetSection = widgetSection,
- dialogFactory = dialogFactory,
+ modifier = modifier.horizontalNestedScrollToScene(),
)
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt
index c60e11e..c25a45d 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt
@@ -16,7 +16,6 @@
package com.android.systemui.keyguard.ui.composable
-import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.Crossfade
import androidx.compose.animation.core.tween
@@ -53,6 +52,7 @@
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerMessageAreaViewModel
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel
+import com.android.systemui.log.LongPressHandlingViewLogger
import com.android.systemui.res.R
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -73,8 +73,6 @@
initialValue = null
)
- BackHandler(enabled = isVisible) { alternateBouncerDependencies.viewModel.onBackRequested() }
-
AnimatedVisibility(
visible = isVisible,
enter = fadeIn(),
@@ -100,6 +98,7 @@
Box {
DeviceEntryIcon(
viewModel = alternateBouncerDependencies.udfpsIconViewModel,
+ logger = alternateBouncerDependencies.logger,
modifier =
Modifier.width { udfpsLocation.width }
.height { udfpsLocation.height }
@@ -154,13 +153,14 @@
@Composable
private fun DeviceEntryIcon(
viewModel: AlternateBouncerUdfpsIconViewModel,
+ logger: LongPressHandlingViewLogger,
modifier: Modifier = Modifier,
) {
AndroidView(
modifier = modifier,
factory = { context ->
val view =
- DeviceEntryIconView(context, null).apply {
+ DeviceEntryIconView(context, null, logger = logger).apply {
id = R.id.alternate_bouncer_udfps_icon_view
contentDescription =
context.resources.getString(R.string.accessibility_fingerprint_label)
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt
index 5f600d3..c7c29f9 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt
@@ -24,7 +24,7 @@
import com.android.compose.animation.scene.UserActionResult
import com.android.compose.animation.scene.animateContentFloatAsState
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenSceneActionsViewModel
+import com.android.systemui.keyguard.ui.viewmodel.LockscreenUserActionsViewModel
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.qs.ui.composable.QuickSettings
import com.android.systemui.scene.shared.model.Scenes
@@ -38,17 +38,16 @@
class LockscreenScene
@Inject
constructor(
- actionsViewModelFactory: LockscreenSceneActionsViewModel.Factory,
+ actionsViewModelFactory: LockscreenUserActionsViewModel.Factory,
private val lockscreenContent: Lazy<LockscreenContent>,
) : ExclusiveActivatable(), Scene {
override val key = Scenes.Lockscreen
- private val actionsViewModel: LockscreenSceneActionsViewModel by lazy {
+ private val actionsViewModel: LockscreenUserActionsViewModel by lazy {
actionsViewModelFactory.create()
}
- override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
- actionsViewModel.actions
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
override suspend fun onActivated(): Nothing {
actionsViewModel.activate()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt
index 3e73057..8d5189e 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt
@@ -73,9 +73,7 @@
val isShadeLayoutWide by viewModel.isShadeLayoutWide.collectAsStateWithLifecycle()
val unfoldTranslations by viewModel.unfoldTranslations.collectAsStateWithLifecycle()
val areNotificationsVisible by
- viewModel
- .areNotificationsVisible(contentKey)
- .collectAsStateWithLifecycle(initialValue = false)
+ viewModel.areNotificationsVisible().collectAsStateWithLifecycle(initialValue = false)
val isBypassEnabled by viewModel.isBypassEnabled.collectAsStateWithLifecycle()
if (isBypassEnabled) {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt
index 4129c25..a525f36 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt
@@ -18,7 +18,6 @@
import android.content.Context
import android.util.DisplayMetrics
-import android.view.View
import android.view.WindowManager
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@@ -45,9 +44,11 @@
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryBackgroundViewModel
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryForegroundViewModel
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LongPressHandlingViewLogger
+import com.android.systemui.log.dagger.LongPressTouchLog
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.res.R
-import com.android.systemui.shade.NotificationPanelView
import com.android.systemui.statusbar.VibratorHelper
import dagger.Lazy
import javax.inject.Inject
@@ -66,7 +67,7 @@
private val deviceEntryBackgroundViewModel: Lazy<DeviceEntryBackgroundViewModel>,
private val falsingManager: Lazy<FalsingManager>,
private val vibratorHelper: Lazy<VibratorHelper>,
- private val notificationPanelView: NotificationPanelView,
+ @LongPressTouchLog private val logBuffer: LogBuffer,
) {
@Composable
fun SceneScope.LockIcon(overrideColor: Color? = null, modifier: Modifier = Modifier) {
@@ -74,29 +75,30 @@
return
}
- notificationPanelView.findViewById<View?>(R.id.lock_icon_view)?.let {
- notificationPanelView.removeView(it)
- }
-
val context = LocalContext.current
AndroidView(
factory = { context ->
val view =
if (DeviceEntryUdfpsRefactor.isEnabled) {
- DeviceEntryIconView(context, null).apply {
- id = R.id.device_entry_icon_view
- DeviceEntryIconViewBinder.bind(
- applicationScope,
- this,
- deviceEntryIconViewModel.get(),
- deviceEntryForegroundViewModel.get(),
- deviceEntryBackgroundViewModel.get(),
- falsingManager.get(),
- vibratorHelper.get(),
- overrideColor,
+ DeviceEntryIconView(
+ context,
+ null,
+ logger = LongPressHandlingViewLogger(logBuffer, tag = TAG)
)
- }
+ .apply {
+ id = R.id.device_entry_icon_view
+ DeviceEntryIconViewBinder.bind(
+ applicationScope,
+ this,
+ deviceEntryIconViewModel.get(),
+ deviceEntryForegroundViewModel.get(),
+ deviceEntryBackgroundViewModel.get(),
+ falsingManager.get(),
+ vibratorHelper.get(),
+ overrideColor,
+ )
+ }
} else {
// KeyguardBottomAreaRefactor.isEnabled
LockIconView(context, null).apply {
@@ -185,6 +187,10 @@
return IntRect(center, radius)
}
+
+ companion object {
+ private const val TAG = "LockSection"
+ }
}
private val LockIconElementKey = ElementKey("LockIcon")
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt
index 4b3a39b..897a861 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt
@@ -23,11 +23,13 @@
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
-import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.unit.IntOffset
import com.android.compose.nestedscroll.PriorityNestedScrollConnection
+import com.android.systemui.common.ui.compose.windowinsets.LocalRawScreenHeight
+import kotlin.math.max
import kotlin.math.roundToInt
+import kotlin.math.tanh
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@@ -36,6 +38,7 @@
coroutineScope: CoroutineScope,
canScrollForward: () -> Boolean
): Modifier {
+ val screenHeight = LocalRawScreenHeight.current
val overscrollOffset = remember { Animatable(0f) }
val stackNestedScrollConnection = remember {
NotificationStackNestedScrollConnection(
@@ -43,7 +46,13 @@
canScrollForward = canScrollForward,
onScroll = { offsetAvailable ->
coroutineScope.launch {
- overscrollOffset.snapTo(overscrollOffset.value + offsetAvailable * 0.3f)
+ val maxProgress = screenHeight * 0.2f
+ val tilt = 3f
+ var offset =
+ overscrollOffset.value +
+ maxProgress * tanh(x = offsetAvailable / (maxProgress * tilt))
+ offset = max(offset, -1f * maxProgress)
+ overscrollOffset.snapTo(offset)
}
},
onStop = { velocityAvailable ->
@@ -79,13 +88,7 @@
offsetAvailable < 0f && offsetBeforeStart < 0f && !canScrollForward()
},
canStartPostFling = { velocityAvailable -> velocityAvailable < 0f && !canScrollForward() },
- canContinueScroll = { source ->
- if (source == NestedScrollSource.SideEffect) {
- stackOffset() > STACK_OVERSCROLL_FLING_MIN_OFFSET
- } else {
- true
- }
- },
+ canContinueScroll = { stackOffset() > 0f },
canScrollOnFling = true,
onStart = { offsetAvailable -> onStart(offsetAvailable) },
onScroll = { offsetAvailable ->
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
index a2beba8..91ecfc1 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
@@ -667,4 +667,3 @@
private val DEBUG_BOX_COLOR = Color(0f, 1f, 0f, 0.2f)
private const val HUN_SNOOZE_POSITIONAL_THRESHOLD_FRACTION = 0.25f
private const val HUN_SNOOZE_VELOCITY_THRESHOLD = -70f
-internal const val STACK_OVERSCROLL_FLING_MIN_OFFSET = -100f
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt
index e4c611e..a22becc 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt
@@ -23,6 +23,8 @@
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.ContentScope
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.rememberViewModel
@@ -39,6 +41,7 @@
import com.android.systemui.statusbar.phone.ui.TintedIconManager
import dagger.Lazy
import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
@SysUISingleton
class NotificationsShadeOverlay
@@ -59,6 +62,8 @@
actionsViewModelFactory.create()
}
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
+
override suspend fun activate(): Nothing {
actionsViewModel.activate()
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt
index ea3f066..1f4cd04 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt
@@ -29,7 +29,7 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.lifecycle.rememberViewModel
-import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeSceneActionsViewModel
+import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeUserActionsViewModel
import com.android.systemui.scene.session.ui.composable.SaveableSession
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.composable.Scene
@@ -49,7 +49,7 @@
class NotificationsShadeScene
@Inject
constructor(
- private val actionsViewModelFactory: NotificationsShadeSceneActionsViewModel.Factory,
+ private val actionsViewModelFactory: NotificationsShadeUserActionsViewModel.Factory,
private val shadeHeaderViewModelFactory: ShadeHeaderViewModel.Factory,
private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory,
private val tintedIconManagerFactory: TintedIconManager.Factory,
@@ -61,12 +61,11 @@
override val key = Scenes.NotificationsShade
- private val actionsViewModel: NotificationsShadeSceneActionsViewModel by lazy {
+ private val actionsViewModel: NotificationsShadeUserActionsViewModel by lazy {
actionsViewModelFactory.create()
}
- override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
- actionsViewModel.actions
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
override suspend fun onActivated(): Nothing {
actionsViewModel.activate()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
index 373383f..d34295e 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
@@ -93,8 +93,8 @@
import com.android.systemui.qs.footer.ui.compose.FooterActionsWithAnimatedVisibility
import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaLandscapeTopOffset
import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaOffset.InQS
-import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneActionsViewModel
import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneContentViewModel
+import com.android.systemui.qs.ui.viewmodel.QuickSettingsUserActionsViewModel
import com.android.systemui.res.R
import com.android.systemui.scene.session.ui.composable.SaveableSession
import com.android.systemui.scene.shared.model.Scenes
@@ -125,7 +125,7 @@
private val shadeSession: SaveableSession,
private val notificationStackScrollView: Lazy<NotificationScrollView>,
private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory,
- private val actionsViewModelFactory: QuickSettingsSceneActionsViewModel.Factory,
+ private val actionsViewModelFactory: QuickSettingsUserActionsViewModel.Factory,
private val contentViewModelFactory: QuickSettingsSceneContentViewModel.Factory,
private val tintedIconManagerFactory: TintedIconManager.Factory,
private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory,
@@ -135,12 +135,11 @@
) : ExclusiveActivatable(), Scene {
override val key = Scenes.QuickSettings
- private val actionsViewModel: QuickSettingsSceneActionsViewModel by lazy {
+ private val actionsViewModel: QuickSettingsUserActionsViewModel by lazy {
actionsViewModelFactory.create()
}
- override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
- actionsViewModel.actions
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
override suspend fun onActivated(): Nothing {
actionsViewModel.activate()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
index 988c712..f8d0588 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
@@ -34,6 +34,8 @@
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.scene.ContentScope
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.brightness.ui.compose.BrightnessSliderContainer
import com.android.systemui.compose.modifiers.sysuiResTag
@@ -51,6 +53,7 @@
import com.android.systemui.statusbar.phone.ui.StatusBarIconController
import com.android.systemui.statusbar.phone.ui.TintedIconManager
import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
@SysUISingleton
class QuickSettingsShadeOverlay
@@ -69,6 +72,8 @@
actionsViewModelFactory.create()
}
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
+
override suspend fun activate(): Nothing {
actionsViewModel.activate()
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt
index 9316eb9..e27c7e2 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt
@@ -27,8 +27,8 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.lifecycle.rememberViewModel
-import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeSceneActionsViewModel
import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeSceneContentViewModel
+import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeUserActionsViewModel
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.composable.Scene
import com.android.systemui.shade.ui.composable.ExpandedShadeHeader
@@ -43,7 +43,7 @@
class QuickSettingsShadeScene
@Inject
constructor(
- private val actionsViewModelFactory: QuickSettingsShadeSceneActionsViewModel.Factory,
+ private val actionsViewModelFactory: QuickSettingsShadeUserActionsViewModel.Factory,
private val contentViewModelFactory: QuickSettingsShadeSceneContentViewModel.Factory,
private val shadeHeaderViewModelFactory: ShadeHeaderViewModel.Factory,
private val tintedIconManagerFactory: TintedIconManager.Factory,
@@ -53,12 +53,11 @@
override val key = Scenes.QuickSettingsShade
- private val actionsViewModel: QuickSettingsShadeSceneActionsViewModel by lazy {
+ private val actionsViewModel: QuickSettingsShadeUserActionsViewModel by lazy {
actionsViewModelFactory.create()
}
- override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
- actionsViewModel.actions
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
override suspend fun onActivated(): Nothing {
actionsViewModel.activate()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/ActionableContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/ActionableContent.kt
new file mode 100644
index 0000000..8fe6893
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/ActionableContent.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.scene.ui.composable
+
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
+import kotlinx.coroutines.flow.Flow
+
+/** Defines interface for content that can respond to user-actions. */
+interface ActionableContent {
+ /**
+ * The mapping between [UserAction] and destination [UserActionResult]s.
+ *
+ * When the scene framework detects a user action, if the current scene has a map entry for that
+ * user action, the framework starts a transition to the content specified in the map.
+ *
+ * Once the content is shown, the scene framework will read this property and set up a collector
+ * to watch for new mapping values. For each map entry, the scene framework will set up user
+ * input handling for its [UserAction] and, if such a user action is detected, initiate a
+ * transition to the specified [UserActionResult].
+ *
+ * Note that reading from this method does _not_ mean that any user action has occurred.
+ * Instead, the property is read before any user action/gesture is detected so that the
+ * framework can decide whether to set up gesture/input detectors/listeners in case user actions
+ * of the given types ever occur.
+ *
+ * A missing value for a specific [UserAction] means that the user action of the given type is
+ * not currently active in the top-most content (in z-index order) and should be ignored by the
+ * framework until the top-most content changes.
+ */
+ val userActions: Flow<Map<UserAction, UserActionResult>>
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt
index 6fb4724..ae5dd8a 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt
@@ -33,7 +33,7 @@
import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaLandscapeTopOffset
import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaOffset.Default
import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.scene.ui.viewmodel.GoneSceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.GoneUserActionsViewModel
import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
import dagger.Lazy
@@ -50,14 +50,13 @@
constructor(
private val notificationStackScrolLView: Lazy<NotificationScrollView>,
private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory,
- private val viewModelFactory: GoneSceneActionsViewModel.Factory,
+ private val viewModelFactory: GoneUserActionsViewModel.Factory,
) : ExclusiveActivatable(), Scene {
override val key = Scenes.Gone
- private val actionsViewModel: GoneSceneActionsViewModel by lazy { viewModelFactory.create() }
+ private val actionsViewModel: GoneUserActionsViewModel by lazy { viewModelFactory.create() }
- override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
- actionsViewModel.actions
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
override suspend fun onActivated(): Nothing {
actionsViewModel.activate()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Overlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Overlay.kt
index d62befd..609ce90 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Overlay.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Overlay.kt
@@ -18,9 +18,14 @@
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import com.android.compose.animation.scene.Back
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.OverlayKey
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.lifecycle.Activatable
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOf
/**
* Defines interface for classes that can describe an "overlay".
@@ -29,9 +34,17 @@
* container takes care of rendering any current overlays and allowing overlays to be shown, hidden,
* or replaced based on a user action.
*/
-interface Overlay : Activatable {
+interface Overlay : Activatable, ActionableContent {
/** Uniquely-identifying key for this overlay. The key must be unique within its container. */
val key: OverlayKey
+ /**
+ * The user actions supported by this overlay.
+ *
+ * @see [ActionableContent.userActions]
+ */
+ override val userActions: Flow<Map<UserAction, UserActionResult>>
+ get() = flowOf(mapOf(Back to UserActionResult.HideOverlay(key)))
+
@Composable fun ContentScope.Content(modifier: Modifier)
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Scene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Scene.kt
index 5319ec3..8d8ab8e 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Scene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Scene.kt
@@ -20,10 +20,7 @@
import androidx.compose.ui.Modifier
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.SceneScope
-import com.android.compose.animation.scene.UserAction
-import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.lifecycle.Activatable
-import kotlinx.coroutines.flow.Flow
/**
* Defines interface for classes that can describe a "scene".
@@ -33,32 +30,10 @@
* based on either user action (for example, swiping down while on the lock screen scene may switch
* to the shade scene).
*/
-interface Scene : Activatable {
+interface Scene : Activatable, ActionableContent {
/** Uniquely-identifying key for this scene. The key must be unique within its container. */
val key: SceneKey
- /**
- * The mapping between [UserAction] and destination [UserActionResult]s.
- *
- * When the scene framework detects a user action, if the current scene has a map entry for that
- * user action, the framework starts a transition to the scene in the map.
- *
- * Once the [Scene] becomes the current one, the scene framework will read this property and set
- * up a collector to watch for new mapping values. If every map entry provided by the scene, the
- * framework will set up user input handling for its [UserAction] and, if such a user action is
- * detected, initiate a transition to the specified [UserActionResult].
- *
- * Note that reading from this method does _not_ mean that any user action has occurred.
- * Instead, the property is read before any user action/gesture is detected so that the
- * framework can decide whether to set up gesture/input detectors/listeners in case user actions
- * of the given types ever occur.
- *
- * Note that a missing value for a specific [UserAction] means that the user action of the given
- * type is not currently active in the scene and should be ignored by the framework, while the
- * current scene is this one.
- */
- val destinationScenes: Flow<Map<UserAction, UserActionResult>>
-
@Composable fun SceneScope.Content(modifier: Modifier)
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
index 851fa3f..df101c5 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
@@ -84,7 +84,6 @@
enableInterruptions = false,
)
}
- val currentSceneKey = state.transitionState.currentScene
DisposableEffect(state) {
val dataSource = SceneTransitionLayoutDataSource(state, coroutineScope)
@@ -97,19 +96,26 @@
onDispose { viewModel.setTransitionState(null) }
}
+ val actionableContentKey =
+ viewModel.getActionableContentKey(state.currentScene, state.currentOverlays, overlayByKey)
val userActionsByContentKey: MutableMap<ContentKey, Map<UserAction, UserActionResult>> =
remember {
mutableStateMapOf()
}
- // TODO(b/359173565): Add overlay user actions when the API is final.
- LaunchedEffect(currentSceneKey) {
+ LaunchedEffect(actionableContentKey) {
try {
- sceneByKey[currentSceneKey]?.destinationScenes?.collectLatest { userActions ->
- userActionsByContentKey[currentSceneKey] =
+ val actionableContent: ActionableContent =
+ checkNotNull(
+ overlayByKey[actionableContentKey] ?: sceneByKey[actionableContentKey]
+ ) {
+ "invalid ContentKey: $actionableContentKey"
+ }
+ actionableContent.userActions.collectLatest { userActions ->
+ userActionsByContentKey[actionableContentKey] =
viewModel.resolveSceneFamilies(userActions)
}
} finally {
- userActionsByContentKey[currentSceneKey] = emptyMap()
+ userActionsByContentKey[actionableContentKey] = emptyMap()
}
}
@@ -122,7 +128,11 @@
}
},
) {
- SceneTransitionLayout(state = state, modifier = modifier.fillMaxSize()) {
+ SceneTransitionLayout(
+ state = state,
+ modifier = modifier.fillMaxSize(),
+ swipeSourceDetector = viewModel.edgeDetector,
+ ) {
sceneByKey.forEach { (sceneKey, scene) ->
scene(
key = sceneKey,
@@ -139,13 +149,16 @@
}
}
}
- overlayByKey.forEach { (overlayKey, composableOverlay) ->
+ overlayByKey.forEach { (overlayKey, overlay) ->
overlay(
key = overlayKey,
userActions = userActionsByContentKey.getOrDefault(overlayKey, emptyMap())
) {
+ // Activate the overlay.
+ LaunchedEffect(overlay) { overlay.activate() }
+
// Render the overlay.
- with(composableOverlay) { this@overlay.Content(Modifier) }
+ with(overlay) { this@overlay.Content(Modifier) }
}
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
index a0ebca2..5a350a6 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
@@ -2,6 +2,7 @@
import androidx.compose.foundation.gestures.Orientation
import com.android.compose.animation.scene.ProgressConverter
+import com.android.compose.animation.scene.TransitionKey
import com.android.compose.animation.scene.transitions
import com.android.systemui.bouncer.ui.composable.Bouncer
import com.android.systemui.notifications.ui.composable.Notifications
@@ -9,6 +10,7 @@
import com.android.systemui.scene.shared.model.TransitionKeys.SlightlyFasterShadeCollapse
import com.android.systemui.scene.shared.model.TransitionKeys.ToSplitShade
import com.android.systemui.scene.ui.composable.transitions.bouncerToGoneTransition
+import com.android.systemui.scene.ui.composable.transitions.bouncerToLockscreenPreview
import com.android.systemui.scene.ui.composable.transitions.goneToNotificationsShadeTransition
import com.android.systemui.scene.ui.composable.transitions.goneToQuickSettingsShadeTransition
import com.android.systemui.scene.ui.composable.transitions.goneToQuickSettingsTransition
@@ -59,6 +61,14 @@
}
from(Scenes.Lockscreen, to = Scenes.Bouncer) { lockscreenToBouncerTransition() }
+ from(
+ Scenes.Lockscreen,
+ to = Scenes.Bouncer,
+ key = TransitionKey.PredictiveBack,
+ reversePreview = { bouncerToLockscreenPreview() }
+ ) {
+ lockscreenToBouncerTransition()
+ }
from(Scenes.Lockscreen, to = Scenes.Communal) { lockscreenToCommunalTransition() }
from(Scenes.Lockscreen, to = Scenes.NotificationsShade) {
lockscreenToNotificationsShadeTransition()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToBouncerTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToBouncerTransition.kt
index 022eb1f..ac54896 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToBouncerTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToBouncerTransition.kt
@@ -1,5 +1,6 @@
package com.android.systemui.scene.ui.composable.transitions
+import androidx.compose.animation.core.CubicBezierEasing
import androidx.compose.animation.core.tween
import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.TransitionBuilder
@@ -18,3 +19,9 @@
fade(Bouncer.Elements.Content)
}
}
+
+fun TransitionBuilder.bouncerToLockscreenPreview() {
+ fractionRange(easing = CubicBezierEasing(0.1f, 0.1f, 0f, 1f)) {
+ scaleDraw(Bouncer.Elements.Content, scaleY = 0.8f, scaleX = 0.8f)
+ }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToCommunalTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToCommunalTransition.kt
index 5401936..826a255 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToCommunalTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToCommunalTransition.kt
@@ -19,14 +19,19 @@
import androidx.compose.animation.core.tween
import com.android.compose.animation.scene.Edge
import com.android.compose.animation.scene.TransitionBuilder
+import com.android.systemui.communal.ui.compose.AllElements
+import com.android.systemui.communal.ui.compose.Communal
import com.android.systemui.scene.shared.model.Scenes
fun TransitionBuilder.lockscreenToCommunalTransition() {
- spec = tween(durationMillis = 500)
+ spec = tween(durationMillis = 1000)
- // Translate lockscreen to the left.
+ // Translate lockscreen to the start direction.
translate(Scenes.Lockscreen.rootElementKey, Edge.Start)
- // Translate communal from the right.
- translate(Scenes.Communal.rootElementKey, Edge.End)
+ // Translate communal hub grid from the end direction.
+ translate(Communal.Elements.Grid, Edge.End)
+
+ // Fade all communal hub elements.
+ timestampRange(startMillis = 167, endMillis = 334) { fade(AllElements) }
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
index 5fcf522..df22264 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
@@ -108,8 +108,8 @@
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.composable.Scene
import com.android.systemui.shade.shared.model.ShadeMode
-import com.android.systemui.shade.ui.viewmodel.ShadeSceneActionsViewModel
import com.android.systemui.shade.ui.viewmodel.ShadeSceneContentViewModel
+import com.android.systemui.shade.ui.viewmodel.ShadeUserActionsViewModel
import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
import com.android.systemui.statusbar.phone.StatusBarLocation
@@ -154,7 +154,7 @@
constructor(
private val shadeSession: SaveableSession,
private val notificationStackScrollView: Lazy<NotificationScrollView>,
- private val actionsViewModelFactory: ShadeSceneActionsViewModel.Factory,
+ private val actionsViewModelFactory: ShadeUserActionsViewModel.Factory,
private val contentViewModelFactory: ShadeSceneContentViewModel.Factory,
private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory,
private val tintedIconManagerFactory: TintedIconManager.Factory,
@@ -167,7 +167,7 @@
override val key = Scenes.Shade
- private val actionsViewModel: ShadeSceneActionsViewModel by lazy {
+ private val actionsViewModel: ShadeUserActionsViewModel by lazy {
actionsViewModelFactory.create()
}
@@ -175,8 +175,7 @@
actionsViewModel.activate()
}
- override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
- actionsViewModel.actions
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
@Composable
override fun SceneScope.Content(
@@ -304,6 +303,8 @@
viewModel.qsSceneAdapter,
)
}
+ val shadeHorizontalPadding =
+ dimensionResource(id = R.dimen.notification_panel_margin_horizontal)
val shadeMeasurePolicy =
remember(mediaInRow) {
SingleShadeMeasurePolicy(
@@ -355,6 +356,7 @@
Box(
Modifier.element(QuickSettings.Elements.QuickQuickSettings)
.layoutId(SingleShadeMeasurePolicy.LayoutId.QuickSettings)
+ .padding(horizontal = shadeHorizontalPadding)
) {
QuickSettings(
viewModel.qsSceneAdapter,
@@ -382,7 +384,9 @@
shouldPunchHoleBehindScrim = shouldPunchHoleBehindScrim,
onEmptySpaceClick =
viewModel::onEmptySpaceClicked.takeIf { isEmptySpaceClickable },
- modifier = Modifier.layoutId(SingleShadeMeasurePolicy.LayoutId.Notifications),
+ modifier =
+ Modifier.layoutId(SingleShadeMeasurePolicy.LayoutId.Notifications)
+ .padding(horizontal = shadeHorizontalPadding),
)
},
measurePolicy = shadeMeasurePolicy,
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
index 4aa50b5..b30f2b7 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
@@ -399,26 +399,53 @@
val fromValue = sharedValue[transition.fromContent]
val toValue = sharedValue[transition.toContent]
- return if (fromValue != null && toValue != null) {
- if (fromValue == toValue) {
- // Optimization: avoid reading progress if the values are the same, so we don't
- // relayout/redraw for nothing.
- fromValue
- } else {
- val overscrollSpec = transition.currentOverscrollSpec
- val progress =
- when {
- overscrollSpec == null -> {
- if (canOverflow) transition.progress
- else transition.progress.fastCoerceIn(0f, 1f)
- }
- overscrollSpec.content == transition.toContent -> 1f
- else -> 0f
- }
+ if (fromValue == null && toValue == null) {
+ return null
+ }
- sharedValue.type.lerp(fromValue, toValue, progress)
+ if (fromValue != null && toValue != null) {
+ return interpolateSharedValue(fromValue, toValue, transition, sharedValue)
+ }
+
+ if (transition is TransitionState.Transition.ReplaceOverlay) {
+ val currentSceneValue = sharedValue[transition.currentScene]
+ if (currentSceneValue != null) {
+ return interpolateSharedValue(
+ fromValue = fromValue ?: currentSceneValue,
+ toValue = toValue ?: currentSceneValue,
+ transition,
+ sharedValue,
+ )
}
- } else fromValue ?: toValue
+ }
+
+ return fromValue ?: toValue
+ }
+
+ private fun interpolateSharedValue(
+ fromValue: T,
+ toValue: T,
+ transition: TransitionState.Transition,
+ sharedValue: SharedValue<T, *>,
+ ): T? {
+ if (fromValue == toValue) {
+ // Optimization: avoid reading progress if the values are the same, so we don't
+ // relayout/redraw for nothing.
+ return fromValue
+ }
+
+ val overscrollSpec = transition.currentOverscrollSpec
+ val progress =
+ when {
+ overscrollSpec == null -> {
+ if (canOverflow) transition.progress
+ else transition.progress.fastCoerceIn(0f, 1f)
+ }
+ overscrollSpec.content == transition.toContent -> 1f
+ else -> 0f
+ }
+
+ return sharedValue.type.lerp(fromValue, toValue, progress)
}
private fun transition(sharedValue: SharedValue<T, Delta>): TransitionState.Transition? {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
index 24fef71..007b84a 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
@@ -190,14 +190,12 @@
private fun computeSwipes(startedPosition: Offset?, pointersDown: Int): Swipes {
val fromSource =
startedPosition?.let { position ->
- layoutImpl.swipeSourceDetector
- .source(
- layoutImpl.lastSize,
- position.round(),
- layoutImpl.density,
- orientation,
- )
- ?.resolve(layoutImpl.layoutDirection)
+ layoutImpl.swipeSourceDetector.source(
+ layoutImpl.lastSize,
+ position.round(),
+ layoutImpl.density,
+ orientation,
+ )
}
val upOrLeft =
@@ -397,14 +395,8 @@
return 0f
}
- fun animateTo(targetContent: T) {
- swipeAnimation.animateOffset(
- initialVelocity = velocity,
- targetContent = targetContent,
- )
- }
-
val fromContent = swipeAnimation.fromContent
+ val consumedVelocity: Float
if (canChangeContent) {
// If we are halfway between two contents, we check what the target will be based on the
// velocity and offset of the transition, then we launch the animation.
@@ -429,18 +421,16 @@
} else {
fromContent
}
-
- animateTo(targetContent = targetContent)
+ consumedVelocity = swipeAnimation.animateOffset(velocity, targetContent = targetContent)
} else {
// We are doing an overscroll preview animation between scenes.
check(fromContent == swipeAnimation.currentContent) {
"canChangeContent is false but currentContent != fromContent"
}
- animateTo(targetContent = fromContent)
+ consumedVelocity = swipeAnimation.animateOffset(velocity, targetContent = fromContent)
}
- // The onStop animation consumes any remaining velocity.
- return velocity
+ return consumedVelocity
}
/**
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/EdgeDetector.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/EdgeDetector.kt
index 97c0cef..edd697b 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/EdgeDetector.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/EdgeDetector.kt
@@ -54,23 +54,23 @@
position: IntOffset,
density: Density,
orientation: Orientation,
- ): Edge? {
+ ): Edge.Resolved? {
val axisSize: Int
val axisPosition: Int
- val topOrLeft: Edge
- val bottomOrRight: Edge
+ val topOrLeft: Edge.Resolved
+ val bottomOrRight: Edge.Resolved
when (orientation) {
Orientation.Horizontal -> {
axisSize = layoutSize.width
axisPosition = position.x
- topOrLeft = Edge.Left
- bottomOrRight = Edge.Right
+ topOrLeft = Edge.Resolved.Left
+ bottomOrRight = Edge.Resolved.Right
}
Orientation.Vertical -> {
axisSize = layoutSize.height
axisPosition = position.y
- topOrLeft = Edge.Top
- bottomOrRight = Edge.Bottom
+ topOrLeft = Edge.Resolved.Top
+ bottomOrRight = Edge.Resolved.Bottom
}
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
index 9b1740d..a076f22 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
@@ -154,11 +154,11 @@
* An element associated to [ElementNode]. Note that this element does not support updates as its
* arguments should always be the same.
*/
-private data class ElementModifier(
- private val layoutImpl: SceneTransitionLayoutImpl,
+internal data class ElementModifier(
+ internal val layoutImpl: SceneTransitionLayoutImpl,
private val currentTransitionStates: List<TransitionState>,
- private val content: Content,
- private val key: ElementKey,
+ internal val content: Content,
+ internal val key: ElementKey,
) : ModifierNodeElement<ElementNode>() {
override fun create(): ElementNode =
ElementNode(layoutImpl, currentTransitionStates, content, key)
@@ -313,10 +313,27 @@
// If this element is not supposed to be laid out now, either because it is not part of any
// ongoing transition or the other content of its transition is overscrolling, then lay out
// the element normally and don't place it.
- val overscrollScene = transition?.currentOverscrollSpec?.content
- val isOtherSceneOverscrolling = overscrollScene != null && overscrollScene != content.key
- if (isOtherSceneOverscrolling) {
- return doNotPlace(measurable, constraints)
+ val overscrollContent = transition?.currentOverscrollSpec?.content
+ if (overscrollContent != null && overscrollContent != content.key) {
+ when (transition) {
+ is TransitionState.Transition.ChangeScene ->
+ return doNotPlace(measurable, constraints)
+
+ // If we are overscrolling an overlay that does not contain an element that is in
+ // the current scene, place it in that scene otherwise the element won't be placed
+ // at all.
+ is TransitionState.Transition.ShowOrHideOverlay,
+ is TransitionState.Transition.ReplaceOverlay -> {
+ if (
+ content.key == transition.currentScene &&
+ overscrollContent !in element.stateByContent
+ ) {
+ return placeNormally(measurable, constraints)
+ } else {
+ return doNotPlace(measurable, constraints)
+ }
+ }
+ }
}
val placeable =
@@ -836,19 +853,32 @@
content,
element.key,
transition,
+ isInContent = { it in element.stateByContent },
)
}
-internal fun shouldPlaceOrComposeSharedElement(
+internal inline fun shouldPlaceOrComposeSharedElement(
layoutImpl: SceneTransitionLayoutImpl,
content: ContentKey,
element: ElementKey,
transition: TransitionState.Transition,
+ isInContent: (ContentKey) -> Boolean,
): Boolean {
- // If we are overscrolling, only place/compose the element in the overscrolling scene.
- val overscrollScene = transition.currentOverscrollSpec?.content
- if (overscrollScene != null) {
- return content == overscrollScene
+ val overscrollContent = transition.currentOverscrollSpec?.content
+ if (overscrollContent != null) {
+ return when (transition) {
+ // If we are overscrolling between scenes, only place/compose the element in the
+ // overscrolling scene.
+ is TransitionState.Transition.ChangeScene -> content == overscrollContent
+
+ // If we are overscrolling an overlay, place/compose the element if [content] is the
+ // overscrolling content or if [content] is the current scene and the overscrolling
+ // overlay does not contain the element.
+ is TransitionState.Transition.ReplaceOverlay,
+ is TransitionState.Transition.ShowOrHideOverlay ->
+ content == overscrollContent ||
+ (content == transition.currentScene && !isInContent(overscrollContent))
+ }
}
val scenePicker = element.contentPicker
@@ -1230,17 +1260,30 @@
// elements follow the finger direction.
val isSharedElement = fromState != null && toState != null
if (isSharedElement && isSharedElementEnabled(element.key, transition)) {
- val start = contentValue(fromState!!)
- val end = contentValue(toState!!)
+ return interpolateSharedElement(
+ transition = transition,
+ contentValue = contentValue,
+ fromState = fromState!!,
+ toState = toState!!,
+ isSpecified = isSpecified,
+ lerp = lerp,
+ )
+ }
- // TODO(b/316901148): Remove checks to isSpecified() once the lookahead pass runs for all
- // nodes before the intermediate layout pass.
- if (!isSpecified(start)) return end
- if (!isSpecified(end)) return start
-
- // Make sure we don't read progress if values are the same and we don't need to interpolate,
- // so we don't invalidate the phase where this is read.
- return if (start == end) start else lerp(start, end, transition.progress)
+ // If we are replacing an overlay and the element is both in a single overlay and in the current
+ // scene, interpolate the state of the element using the current scene as the other scene.
+ if (!isSharedElement && transition is TransitionState.Transition.ReplaceOverlay) {
+ val currentSceneState = element.stateByContent[transition.currentScene]
+ if (currentSceneState != null) {
+ return interpolateSharedElement(
+ transition = transition,
+ contentValue = contentValue,
+ fromState = fromState ?: currentSceneState,
+ toState = toState ?: currentSceneState,
+ isSpecified = isSpecified,
+ lerp = lerp,
+ )
+ }
}
// Get the transformed value, i.e. the target value at the beginning (for entering elements) or
@@ -1383,3 +1426,24 @@
lerp(idleValue, targetValue, rangeProgress)
}
}
+
+private inline fun <T> interpolateSharedElement(
+ transition: TransitionState.Transition,
+ contentValue: (Element.State) -> T,
+ fromState: Element.State,
+ toState: Element.State,
+ isSpecified: (T) -> Boolean,
+ lerp: (T, T, Float) -> T
+): T {
+ val start = contentValue(fromState)
+ val end = contentValue(toState)
+
+ // TODO(b/316901148): Remove checks to isSpecified() once the lookahead pass runs for all
+ // nodes before the intermediate layout pass.
+ if (!isSpecified(start)) return end
+ if (!isSpecified(end)) return start
+
+ // Make sure we don't read progress if values are the same and we don't need to interpolate,
+ // so we don't invalidate the phase where this is read.
+ return if (start == end) start else lerp(start, end, transition.progress)
+}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
index 715222c..471ad3f 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
@@ -194,11 +194,13 @@
is TransitionState.Transition -> {
// During transitions, always compose movable elements in the scene picked by their
// content picker.
+ val contents = element.contentPicker.contents
shouldPlaceOrComposeSharedElement(
layoutImpl,
content,
element,
elementState,
+ isInContent = { contents.contains(it) }
)
}
}
@@ -208,8 +210,8 @@
element: MovableElementKey,
transitionStates: List<TransitionState>,
): TransitionState? {
- val content = element.contentPicker.contents
- return elementState(transitionStates, isInContent = { content.contains(it) })
+ val contents = element.contentPicker.contents
+ return elementState(transitionStates, isInContent = { contents.contains(it) })
}
private fun movableElementContentWhenIdle(
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
index 5780c08..0d05f4e 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
@@ -221,19 +221,59 @@
private suspend fun PointerInputScope.pointerTracker() {
val currentContext = currentCoroutineContext()
awaitPointerEventScope {
+ var velocityPointerId: PointerId? = null
// Intercepts pointer inputs and exposes [PointersInfo], via
// [requireAncestorPointersInfoOwner], to our descendants.
while (currentContext.isActive) {
// During the Initial pass, we receive the event after our ancestors.
- val pointers = awaitPointerEvent(PointerEventPass.Initial).changes
- pointersDown = pointers.countDown()
- if (pointersDown == 0) {
- // There are no more pointers down
- startedPosition = null
- } else if (startedPosition == null) {
- startedPosition = pointers.first().position
- if (enabled()) {
- onFirstPointerDown()
+ val changes = awaitPointerEvent(PointerEventPass.Initial).changes
+ pointersDown = changes.countDown()
+
+ when {
+ // There are no more pointers down.
+ pointersDown == 0 -> {
+ startedPosition = null
+
+ // This is the last pointer up
+ velocityTracker.addPointerInputChange(changes.single())
+ }
+
+ // The first pointer down, startedPosition was not set.
+ startedPosition == null -> {
+ val firstPointerDown = changes.single()
+ velocityPointerId = firstPointerDown.id
+ velocityTracker.resetTracking()
+ velocityTracker.addPointerInputChange(firstPointerDown)
+ startedPosition = firstPointerDown.position
+ if (enabled()) {
+ onFirstPointerDown()
+ }
+ }
+
+ // Changes with at least one pointer
+ else -> {
+ val pointerChange = changes.first()
+
+ // Assuming that the list of changes doesn't have two changes with the same
+ // id (PointerId), we can check:
+ // - If the first change has `id` equals to `velocityPointerId` (this should
+ // always be true unless the pointer has been removed).
+ // - If it does, we've found our change event (assuming there aren't any
+ // others changes with the same id in this PointerEvent - not checked).
+ // - If it doesn't, we can check that the change with that id isn't in first
+ // place (which should never happen - this will crash).
+ check(
+ pointerChange.id == velocityPointerId ||
+ !changes.fastAny { it.id == velocityPointerId }
+ ) {
+ "$velocityPointerId is present, but not the first: $changes"
+ }
+
+ // If the previous pointer has been removed, we use the first available
+ // change to keep tracking the velocity.
+ velocityPointerId = pointerChange.id
+
+ velocityTracker.addPointerInputChange(pointerChange)
}
}
}
@@ -253,11 +293,9 @@
orientation = orientation,
startDragImmediately = startDragImmediately,
onDragStart = { startedPosition, overSlop, pointersDown ->
- velocityTracker.resetTracking()
onDragStarted(startedPosition, overSlop, pointersDown)
},
- onDrag = { controller, change, amount ->
- velocityTracker.addPointerInputChange(change)
+ onDrag = { controller, amount ->
dispatchScrollEvents(
availableOnPreScroll = amount,
onScroll = { controller.onDrag(it) },
@@ -403,7 +441,7 @@
startDragImmediately: (startedPosition: Offset) -> Boolean,
onDragStart:
(startedPosition: Offset, overSlop: Float, pointersDown: Int) -> DragController,
- onDrag: (controller: DragController, change: PointerInputChange, dragAmount: Float) -> Unit,
+ onDrag: (controller: DragController, dragAmount: Float) -> Unit,
onDragEnd: (controller: DragController) -> Unit,
onDragCancel: (controller: DragController) -> Unit,
swipeDetector: SwipeDetector,
@@ -482,14 +520,14 @@
val successful: Boolean
try {
- onDrag(controller, drag, overSlop)
+ onDrag(controller, overSlop)
successful =
drag(
initialPointerId = drag.id,
hasDragged = { it.positionChangeIgnoreConsumed().toFloat() != 0f },
onDrag = {
- onDrag(controller, it, it.positionChange().toFloat())
+ onDrag(controller, it.positionChange().toFloat())
it.consume()
},
onIgnoredEvent = {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt
index bd21a69..8ae3a11 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt
@@ -46,8 +46,21 @@
}
}
+ /** The current overlays. */
+ fun currentOverlays(): Flow<Set<OverlayKey>> {
+ return when (this) {
+ is Idle -> flowOf(currentOverlays)
+ is Transition -> currentOverlays
+ }
+ }
+
/** No transition/animation is currently running. */
- data class Idle(val currentScene: SceneKey) : ObservableTransitionState
+ data class Idle
+ @JvmOverloads
+ constructor(
+ val currentScene: SceneKey,
+ val currentOverlays: Set<OverlayKey> = emptySet(),
+ ) : ObservableTransitionState
/** There is a transition animating between two scenes. */
sealed class Transition(
@@ -94,7 +107,7 @@
val fromScene: SceneKey,
val toScene: SceneKey,
val currentScene: Flow<SceneKey>,
- currentOverlays: Flow<Set<OverlayKey>>,
+ currentOverlays: Set<OverlayKey>,
progress: Flow<Float>,
isInitiatedByUserInput: Boolean,
isUserInputOngoing: Flow<Boolean>,
@@ -104,7 +117,7 @@
Transition(
fromScene,
toScene,
- currentOverlays,
+ flowOf(currentOverlays),
progress,
isInitiatedByUserInput,
isUserInputOngoing,
@@ -169,7 +182,7 @@
isUserInputOngoing: Flow<Boolean>,
previewProgress: Flow<Float> = flowOf(0f),
isInPreviewStage: Flow<Boolean> = flowOf(false),
- currentOverlays: Flow<Set<OverlayKey>> = flowOf(emptySet()),
+ currentOverlays: Set<OverlayKey> = emptySet(),
): ChangeScene {
return ChangeScene(
fromScene,
@@ -205,13 +218,17 @@
fun SceneTransitionLayoutState.observableTransitionState(): Flow<ObservableTransitionState> {
return snapshotFlow {
when (val state = transitionState) {
- is TransitionState.Idle -> ObservableTransitionState.Idle(state.currentScene)
+ is TransitionState.Idle ->
+ ObservableTransitionState.Idle(
+ state.currentScene,
+ state.currentOverlays,
+ )
is TransitionState.Transition.ChangeScene -> {
ObservableTransitionState.Transition.ChangeScene(
fromScene = state.fromScene,
toScene = state.toScene,
currentScene = snapshotFlow { state.currentScene },
- currentOverlays = flowOf(state.currentOverlays),
+ currentOverlays = state.currentOverlays,
progress = snapshotFlow { state.progress },
isInitiatedByUserInput = state.isInitiatedByUserInput,
isUserInputOngoing = snapshotFlow { state.isUserInputOngoing },
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
index 094f20e..004bb40 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
@@ -379,6 +379,10 @@
return this to UserActionResult(toScene = scene)
}
+ infix fun to(overlay: OverlayKey): Pair<UserAction, UserActionResult> {
+ return this to UserActionResult(toOverlay = overlay)
+ }
+
/** Resolve this into a [Resolved] user action given [layoutDirection]. */
internal abstract fun resolve(layoutDirection: LayoutDirection): Resolved
@@ -475,7 +479,7 @@
position: IntOffset,
density: Density,
orientation: Orientation,
- ): SwipeSource?
+ ): SwipeSource.Resolved?
}
/** The result of performing a [UserAction]. */
@@ -550,6 +554,22 @@
*/
requiresFullDistanceSwipe: Boolean = false,
): UserActionResult = ChangeScene(toScene, transitionKey, requiresFullDistanceSwipe)
+
+ /** A [UserActionResult] that shows [toOverlay]. */
+ operator fun invoke(
+ /** The overlay we should be transitioning to during the [UserAction]. */
+ toOverlay: OverlayKey,
+
+ /** The key of the transition that should be used. */
+ transitionKey: TransitionKey? = null,
+
+ /**
+ * If `true`, the swipe will be committed if only if the user swiped at least the swipe
+ * distance, i.e. the transition progress was already equal to or bigger than 100% when
+ * the user released their finger.
+ */
+ requiresFullDistanceSwipe: Boolean = false,
+ ): UserActionResult = ShowOverlay(toOverlay, transitionKey, requiresFullDistanceSwipe)
}
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt
index 2a09a77..966bda4 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt
@@ -312,11 +312,16 @@
fun isAnimatingOffset(): Boolean = offsetAnimation != null
+ /**
+ * Animate the offset to a [targetContent], using the [initialVelocity] and an optional [spec]
+ *
+ * @return the velocity consumed
+ */
fun animateOffset(
initialVelocity: Float,
targetContent: T,
spec: AnimationSpec<Float>? = null,
- ) {
+ ): Float {
check(!isAnimatingOffset()) { "SwipeAnimation.animateOffset() can only be called once" }
val initialProgress = progress
@@ -374,7 +379,7 @@
if (skipAnimation) {
// Unblock the job.
offsetAnimationRunnable.complete(null)
- return
+ return 0f
}
val isTargetGreater = targetOffset > animatable.value
@@ -424,6 +429,9 @@
/* Ignore. */
}
}
+
+ // This animation always consumes the whole available velocity
+ return initialVelocity
}
/** An exception thrown during the animation to stop it immediately. */
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/testing/ElementStateAccess.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/testing/ElementStateAccess.kt
new file mode 100644
index 0000000..cade9bf
--- /dev/null
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/testing/ElementStateAccess.kt
@@ -0,0 +1,51 @@
+/*
+ * 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.compose.animation.scene.testing
+
+import androidx.compose.ui.semantics.SemanticsNode
+import com.android.compose.animation.scene.Element
+import com.android.compose.animation.scene.Element.Companion.AlphaUnspecified
+import com.android.compose.animation.scene.ElementModifier
+import com.android.compose.animation.scene.Scale
+
+val SemanticsNode.lastAlphaForTesting: Float?
+ get() = elementState.lastAlpha.takeIf { it != AlphaUnspecified }
+
+val SemanticsNode.lastScaleForTesting: Scale?
+ get() = elementState.lastScale.takeIf { it != Scale.Unspecified }
+
+private val SemanticsNode.elementState: Element.State
+ get() {
+ val elementModifier =
+ layoutInfo
+ .getModifierInfo()
+ .map { it.modifier }
+ .filterIsInstance<ElementModifier>()
+ .firstOrNull()
+ requireNotNull(elementModifier) {
+ "No ElementModifier found. Did you use the Modifier.element(...)?"
+ }
+ return with(elementModifier) {
+ val element =
+ requireNotNull(layoutImpl.elements[key]) {
+ "No element found in STL layout with key: ${key.testTag}"
+ }
+ requireNotNull(element.stateByContent[content.key]) {
+ "No state found for given content key: ${content.key.testTag}"
+ }
+ }
+ }
diff --git a/packages/SystemUI/compose/scene/src/com/android/systemui/communal/ui/compose/CommunalSwipeDetector.kt b/packages/SystemUI/compose/scene/src/com/android/systemui/communal/ui/compose/CommunalSwipeDetector.kt
index 3fda9b8..41b015a 100644
--- a/packages/SystemUI/compose/scene/src/com/android/systemui/communal/ui/compose/CommunalSwipeDetector.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/systemui/communal/ui/compose/CommunalSwipeDetector.kt
@@ -33,7 +33,7 @@
* SwipeSourceDetector} to enable fullscreen swipe handling to transition to and from the glanceable
* hub.
*/
-class CommunalSwipeDetector(private var lastDirection: SwipeSource? = null) :
+class CommunalSwipeDetector(private var lastDirection: SwipeSource.Resolved? = null) :
SwipeSourceDetector, SwipeDetector {
companion object {
private const val TRAVEL_RATIO_THRESHOLD = .5f
@@ -44,15 +44,15 @@
position: IntOffset,
density: Density,
orientation: Orientation
- ): SwipeSource? {
+ ): SwipeSource.Resolved? {
return lastDirection
}
override fun detectSwipe(change: PointerInputChange): Boolean {
if (change.positionChange().x > 0) {
- lastDirection = Edge.Left
+ lastDirection = Edge.Resolved.Left
} else {
- lastDirection = Edge.Right
+ lastDirection = Edge.Resolved.Right
}
// Determine whether the ratio of the distance traveled horizontally to the distance
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
index 79f82c9..5b59356 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
@@ -1111,7 +1111,7 @@
assertTransition(fromScene = SceneA, toScene = SceneB, progress = 1f)
// Release the finger.
- dragController.onDragStopped(velocity = -velocityThreshold)
+ dragController.onDragStopped(velocity = -velocityThreshold, expectedConsumed = false)
// Exhaust all coroutines *without advancing the clock*. Given that we are at progress >=
// 100% and that the overscroll on scene B is doing nothing, we are already idle.
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/FixedSizeEdgeDetectorTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/FixedSizeEdgeDetectorTest.kt
index cceaf57..dea9283 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/FixedSizeEdgeDetectorTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/FixedSizeEdgeDetectorTest.kt
@@ -34,7 +34,7 @@
@Test
fun horizontalEdges() {
- fun horizontalEdge(position: Int): Edge? =
+ fun horizontalEdge(position: Int): Edge.Resolved? =
detector.source(
layoutSize,
position = IntOffset(position, 0),
@@ -42,17 +42,17 @@
Orientation.Horizontal,
)
- assertThat(horizontalEdge(0)).isEqualTo(Edge.Left)
- assertThat(horizontalEdge(30)).isEqualTo(Edge.Left)
+ assertThat(horizontalEdge(0)).isEqualTo(Edge.Resolved.Left)
+ assertThat(horizontalEdge(30)).isEqualTo(Edge.Resolved.Left)
assertThat(horizontalEdge(31)).isEqualTo(null)
assertThat(horizontalEdge(69)).isEqualTo(null)
- assertThat(horizontalEdge(70)).isEqualTo(Edge.Right)
- assertThat(horizontalEdge(100)).isEqualTo(Edge.Right)
+ assertThat(horizontalEdge(70)).isEqualTo(Edge.Resolved.Right)
+ assertThat(horizontalEdge(100)).isEqualTo(Edge.Resolved.Right)
}
@Test
fun verticalEdges() {
- fun verticalEdge(position: Int): Edge? =
+ fun verticalEdge(position: Int): Edge.Resolved? =
detector.source(
layoutSize,
position = IntOffset(0, position),
@@ -60,11 +60,11 @@
Orientation.Vertical,
)
- assertThat(verticalEdge(0)).isEqualTo(Edge.Top)
- assertThat(verticalEdge(30)).isEqualTo(Edge.Top)
+ assertThat(verticalEdge(0)).isEqualTo(Edge.Resolved.Top)
+ assertThat(verticalEdge(30)).isEqualTo(Edge.Resolved.Top)
assertThat(verticalEdge(31)).isEqualTo(null)
assertThat(verticalEdge(69)).isEqualTo(null)
- assertThat(verticalEdge(70)).isEqualTo(Edge.Bottom)
- assertThat(verticalEdge(100)).isEqualTo(Edge.Bottom)
+ assertThat(verticalEdge(70)).isEqualTo(Edge.Resolved.Bottom)
+ assertThat(verticalEdge(100)).isEqualTo(Edge.Resolved.Bottom)
}
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt
index d742592..bf192e7 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt
@@ -38,12 +38,15 @@
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalViewConfiguration
+import androidx.compose.ui.test.TouchInjectionScope
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performTouchInput
+import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Velocity
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
+import kotlin.properties.Delegates
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.isActive
import org.junit.Rule
@@ -719,4 +722,88 @@
assertThat(availableOnPreFling).isEqualTo(consumedOnDragStop)
assertThat(availableOnPostFling).isEqualTo(0f)
}
+
+ @Test
+ fun multiPointerOnStopVelocity() {
+ val size = 200f
+ val middle = Offset(size / 2f, size / 2f)
+
+ var stopped = false
+ var lastVelocity = -1f
+ var touchSlop = 0f
+ var density: Density by Delegates.notNull()
+ rule.setContent {
+ touchSlop = LocalViewConfiguration.current.touchSlop
+ density = LocalDensity.current
+ Box(
+ Modifier.size(with(density) { Size(size, size).toDpSize() })
+ .nestedScrollDispatcher()
+ .multiPointerDraggable(
+ orientation = Orientation.Vertical,
+ enabled = { true },
+ startDragImmediately = { false },
+ onDragStarted = { _, _, _ ->
+ SimpleDragController(
+ onDrag = { /* do nothing */ },
+ onStop = {
+ stopped = true
+ lastVelocity = it
+ },
+ )
+ },
+ dispatcher = defaultDispatcher,
+ )
+ )
+ }
+
+ var eventMillis: Long by Delegates.notNull()
+ rule.onRoot().performTouchInput { eventMillis = eventPeriodMillis }
+
+ fun swipeGesture(block: TouchInjectionScope.() -> Unit) {
+ stopped = false
+ rule.onRoot().performTouchInput {
+ down(middle)
+ block()
+ up()
+ }
+ assertThat(stopped).isEqualTo(true)
+ }
+
+ val shortDistance = touchSlop / 2f
+ swipeGesture {
+ moveBy(delta = Offset(0f, shortDistance), delayMillis = eventMillis)
+ moveBy(delta = Offset(0f, shortDistance), delayMillis = eventMillis)
+ }
+ assertThat(lastVelocity).isGreaterThan(0f)
+ assertThat(lastVelocity).isWithin(1f).of((shortDistance / eventMillis) * 1000f)
+
+ val longDistance = touchSlop * 4f
+ swipeGesture {
+ moveBy(delta = Offset(0f, longDistance), delayMillis = eventMillis)
+ moveBy(delta = Offset(0f, longDistance), delayMillis = eventMillis)
+ }
+ assertThat(lastVelocity).isGreaterThan(0f)
+ assertThat(lastVelocity).isWithin(1f).of((longDistance / eventMillis) * 1000f)
+
+ rule.onRoot().performTouchInput {
+ down(pointerId = 0, position = middle)
+ down(pointerId = 1, position = middle)
+ moveBy(pointerId = 0, delta = Offset(0f, longDistance), delayMillis = eventMillis)
+ moveBy(pointerId = 0, delta = Offset(0f, longDistance), delayMillis = eventMillis)
+ // The velocity should be:
+ // (longDistance / eventMillis) pixels/ms
+
+ // 1 pointer left, the second one
+ up(pointerId = 0)
+
+ // After a few events the velocity should be:
+ // (shortDistance / eventMillis) pixels/ms
+ repeat(10) {
+ moveBy(pointerId = 1, delta = Offset(0f, shortDistance), delayMillis = eventMillis)
+ }
+ up(pointerId = 1)
+ }
+ assertThat(lastVelocity).isGreaterThan(0f)
+ assertThat(lastVelocity).isWithin(1f).of((shortDistance / eventMillis) * 1000f)
+ }
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt
index bec2bb2..471362b 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt
@@ -18,14 +18,17 @@
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.tween
+import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
@@ -42,7 +45,12 @@
import com.android.compose.animation.scene.TestOverlays.OverlayB
import com.android.compose.animation.scene.TestScenes.SceneA
import com.android.compose.test.assertSizeIsEqualTo
+import com.android.compose.test.setContentAndCreateMainScope
+import com.android.compose.test.subjects.assertThat
+import com.android.compose.test.transition
+import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -524,4 +532,162 @@
}
}
}
+
+ @Test
+ fun replaceAnimation_elementInCurrentSceneAndOneOverlay() {
+ val sharedIntKey = ValueKey("sharedInt")
+ val sharedIntValueByContent = mutableMapOf<ContentKey, Int>()
+
+ @Composable
+ fun SceneScope.animateContentInt(targetValue: Int) {
+ val animatedValue = animateContentIntAsState(targetValue, sharedIntKey)
+ LaunchedEffect(animatedValue) {
+ try {
+ snapshotFlow { animatedValue.value }
+ .collect { sharedIntValueByContent[contentKey] = it }
+ } finally {
+ sharedIntValueByContent.remove(contentKey)
+ }
+ }
+ }
+
+ rule.testReplaceOverlayTransition(
+ currentSceneContent = {
+ Box(Modifier.size(width = 180.dp, height = 120.dp)) {
+ animateContentInt(targetValue = 1_000)
+ Foo(width = 60.dp, height = 40.dp)
+ }
+ },
+ fromContent = {},
+ fromAlignment = Alignment.TopStart,
+ toContent = {
+ animateContentInt(targetValue = 2_000)
+ Foo(width = 100.dp, height = 80.dp)
+ },
+ transition = {
+ // 4 frames of animation
+ spec = tween(4 * 16, easing = LinearEasing)
+ },
+ ) {
+ // Foo moves from (0,0) with a size of 60x40dp to centered (in a 180x120dp Box) with a
+ // size of 100x80dp, so at (40,20).
+ //
+ // The animated Int goes from 1_000 to 2_000.
+ before {
+ rule
+ .onNode(isElement(TestElements.Foo, content = SceneA))
+ .assertSizeIsEqualTo(60.dp, 40.dp)
+ .assertPositionInRootIsEqualTo(0.dp, 0.dp)
+ rule.onNode(isElement(TestElements.Foo, content = OverlayA)).assertDoesNotExist()
+ rule.onNode(isElement(TestElements.Foo, content = OverlayB)).assertDoesNotExist()
+
+ assertThat(sharedIntValueByContent).containsEntry(SceneA, 1_000)
+ assertThat(sharedIntValueByContent).doesNotContainKey(OverlayA)
+ assertThat(sharedIntValueByContent).doesNotContainKey(OverlayB)
+ }
+
+ at(16) {
+ rule
+ .onNode(isElement(TestElements.Foo, content = SceneA))
+ .assertExists()
+ .assertIsNotDisplayed()
+ rule.onNode(isElement(TestElements.Foo, content = OverlayA)).assertDoesNotExist()
+ rule
+ .onNode(isElement(TestElements.Foo, content = OverlayB))
+ .assertSizeIsEqualTo(70.dp, 50.dp)
+ .assertPositionInRootIsEqualTo(10.dp, 5.dp)
+
+ assertThat(sharedIntValueByContent).containsEntry(SceneA, 1_250)
+ assertThat(sharedIntValueByContent).doesNotContainKey(OverlayA)
+ assertThat(sharedIntValueByContent).containsEntry(OverlayB, 1_250)
+ }
+
+ at(32) {
+ rule
+ .onNode(isElement(TestElements.Foo, content = SceneA))
+ .assertExists()
+ .assertIsNotDisplayed()
+ rule.onNode(isElement(TestElements.Foo, content = OverlayA)).assertDoesNotExist()
+ rule
+ .onNode(isElement(TestElements.Foo, content = OverlayB))
+ .assertSizeIsEqualTo(80.dp, 60.dp)
+ .assertPositionInRootIsEqualTo(20.dp, 10.dp)
+
+ assertThat(sharedIntValueByContent).containsEntry(SceneA, 1_500)
+ assertThat(sharedIntValueByContent).doesNotContainKey(OverlayA)
+ assertThat(sharedIntValueByContent).containsEntry(OverlayB, 1_500)
+ }
+
+ at(48) {
+ rule
+ .onNode(isElement(TestElements.Foo, content = SceneA))
+ .assertExists()
+ .assertIsNotDisplayed()
+ rule.onNode(isElement(TestElements.Foo, content = OverlayA)).assertDoesNotExist()
+ rule
+ .onNode(isElement(TestElements.Foo, content = OverlayB))
+ .assertSizeIsEqualTo(90.dp, 70.dp)
+ .assertPositionInRootIsEqualTo(30.dp, 15.dp)
+
+ assertThat(sharedIntValueByContent).containsEntry(SceneA, 1_750)
+ assertThat(sharedIntValueByContent).doesNotContainKey(OverlayA)
+ assertThat(sharedIntValueByContent).containsEntry(OverlayB, 1_750)
+ }
+
+ after {
+ rule
+ .onNode(isElement(TestElements.Foo, content = SceneA))
+ .assertExists()
+ .assertIsNotDisplayed()
+ rule.onNode(isElement(TestElements.Foo, content = OverlayA)).assertDoesNotExist()
+ rule
+ .onNode(isElement(TestElements.Foo, content = OverlayB))
+ .assertSizeIsEqualTo(100.dp, 80.dp)
+ .assertPositionInRootIsEqualTo(40.dp, 20.dp)
+
+ // Outside of transitions, the value is equal to the target value in each content.
+ assertThat(sharedIntValueByContent).containsEntry(SceneA, 1_000)
+ assertThat(sharedIntValueByContent).doesNotContainKey(OverlayA)
+ assertThat(sharedIntValueByContent).containsEntry(OverlayB, 2_000)
+ }
+ }
+ }
+
+ @Test
+ fun overscrollingOverlay_movableElementNotInOverlay() {
+ val state =
+ rule.runOnUiThread {
+ MutableSceneTransitionLayoutStateImpl(
+ SceneA,
+ transitions {
+ // Make OverlayA overscrollable.
+ overscroll(OverlayA, orientation = Orientation.Horizontal) {
+ translate(ElementKey("elementThatDoesNotExist"), x = 10.dp)
+ }
+ }
+ )
+ }
+
+ val key = MovableElementKey("Foo", contents = setOf(SceneA))
+ val movableElementChildTag = "movableElementChildTag"
+ val scope =
+ rule.setContentAndCreateMainScope {
+ SceneTransitionLayout(state) {
+ scene(SceneA) {
+ MovableElement(key, Modifier) {
+ content { Box(Modifier.testTag(movableElementChildTag).size(100.dp)) }
+ }
+ }
+ overlay(OverlayA) { /* Does not contain the element. */ }
+ }
+ }
+
+ // Overscroll on Overlay A.
+ scope.launch { state.startTransition(transition(SceneA, OverlayA, progress = { 1.5f })) }
+ rule
+ .onNode(hasTestTag(movableElementChildTag) and inContent(SceneA))
+ .assertPositionInRootIsEqualTo(0.dp, 0.dp)
+ .assertSizeIsEqualTo(100.dp)
+ .assertIsDisplayed()
+ }
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
index cd20a29a..d356c25 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
@@ -32,7 +32,7 @@
import com.android.compose.animation.scene.transition.link.StateLink
import com.android.compose.animation.scene.transition.seekToScene
import com.android.compose.test.MonotonicClockTestScope
-import com.android.compose.test.TestTransition
+import com.android.compose.test.TestSceneTransition
import com.android.compose.test.runMonotonicClockTest
import com.android.compose.test.transition
import com.google.common.truth.Truth.assertThat
@@ -556,8 +556,8 @@
@Test
fun multipleTransitions() = runTest {
- val frozenTransitions = mutableSetOf<TestTransition>()
- fun onFreezeAndAnimate(transition: TestTransition): () -> Unit {
+ val frozenTransitions = mutableSetOf<TestSceneTransition>()
+ fun onFreezeAndAnimate(transition: TestSceneTransition): () -> Unit {
// Instead of letting the transition finish when it is frozen, we put the transition in
// the frozenTransitions set so that we can verify that freezeAndAnimateToCurrentState()
// is called when expected and then we call finish() ourselves to finish the
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/testing/ElementStateAccessTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/testing/ElementStateAccessTest.kt
new file mode 100644
index 0000000..e4a87ba
--- /dev/null
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/testing/ElementStateAccessTest.kt
@@ -0,0 +1,75 @@
+/*
+ * 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.compose.animation.scene.testing
+
+import androidx.compose.animation.core.LinearEasing
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.size
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.compose.animation.scene.Scale
+import com.android.compose.animation.scene.TestElements
+import com.android.compose.animation.scene.TestScenes.SceneA
+import com.android.compose.animation.scene.TestScenes.SceneB
+import com.android.compose.animation.scene.testTransition
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ElementStateAccessTest {
+
+ @get:Rule val rule = createComposeRule()
+
+ @Test
+ fun testElementStateAccess() {
+ rule.testTransition(
+ fromSceneContent = { Box(Modifier.element(TestElements.Foo).size(50.dp)) },
+ toSceneContent = { Box(Modifier) },
+ transition = {
+ spec = tween(durationMillis = 16 * 4, easing = LinearEasing)
+ fade(TestElements.Foo)
+ scaleDraw(TestElements.Foo, scaleX = 0f, scaleY = 0f)
+ },
+ fromScene = SceneA,
+ toScene = SceneB,
+ ) {
+ before {
+ val semanticNode = onElement(TestElements.Foo).fetchSemanticsNode()
+ assertThat(semanticNode.lastAlphaForTesting).isEqualTo(1f)
+ assertThat(semanticNode.lastScaleForTesting).isEqualTo(Scale(1f, 1f))
+ }
+
+ at(32) {
+ val semanticNode = onElement(TestElements.Foo).fetchSemanticsNode()
+ assertThat(semanticNode.lastAlphaForTesting).isEqualTo(0.5f)
+ assertThat(semanticNode.lastScaleForTesting).isEqualTo(Scale(0.5f, 0.5f))
+ }
+
+ at(64) {
+ val semanticNode = onElement(TestElements.Foo).fetchSemanticsNode()
+ assertThat(semanticNode.lastAlphaForTesting).isEqualTo(0f)
+ assertThat(semanticNode.lastScaleForTesting).isEqualTo(Scale(0f, 0f))
+ }
+ after { onElement(TestElements.Foo).assertDoesNotExist() }
+ }
+ }
+}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestTransition.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestOverlayTransition.kt
similarity index 77%
copy from packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestTransition.kt
copy to packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestOverlayTransition.kt
index a6a83ee..646cff8 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestTransition.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestOverlayTransition.kt
@@ -18,18 +18,26 @@
import androidx.compose.foundation.gestures.Orientation
import com.android.compose.animation.scene.ContentKey
+import com.android.compose.animation.scene.OverlayKey
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.SceneTransitionLayoutImpl
import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.content.state.TransitionState.Transition
import kotlinx.coroutines.CompletableDeferred
-/** A transition for tests that will be finished once [finish] is called. */
-abstract class TestTransition(
+/** A [Transition.ShowOrHideOverlay] for tests that will be finished once [finish] is called. */
+abstract class TestOverlayTransition(
fromScene: SceneKey,
- toScene: SceneKey,
+ overlay: OverlayKey,
replacedTransition: Transition?,
-) : Transition.ChangeScene(fromScene, toScene, replacedTransition) {
+) :
+ Transition.ShowOrHideOverlay(
+ overlay = overlay,
+ fromOrToScene = fromScene,
+ fromContent = fromScene,
+ toContent = overlay,
+ replacedTransition = replacedTransition,
+ ) {
private val finishCompletable = CompletableDeferred<Unit>()
override suspend fun run() {
@@ -42,11 +50,11 @@
}
}
-/** A utility to easily create a [TestTransition] in tests. */
+/** A utility to easily create a [TestOverlayTransition] in tests. */
fun transition(
- from: SceneKey,
- to: SceneKey,
- current: () -> SceneKey = { to },
+ fromScene: SceneKey,
+ overlay: OverlayKey,
+ isEffectivelyShown: () -> Boolean = { true },
progress: () -> Float = { 0f },
progressVelocity: () -> Float = { 0f },
previewProgress: () -> Float = { 0f },
@@ -58,13 +66,14 @@
isUpOrLeft: Boolean = false,
bouncingContent: ContentKey? = null,
orientation: Orientation = Orientation.Horizontal,
- onFreezeAndAnimate: ((TestTransition) -> Unit)? = null,
+ onFreezeAndAnimate: ((TestOverlayTransition) -> Unit)? = null,
replacedTransition: Transition? = null,
-): TestTransition {
+): TestOverlayTransition {
return object :
- TestTransition(from, to, replacedTransition), TransitionState.HasOverscrollProperties {
- override val currentScene: SceneKey
- get() = current()
+ TestOverlayTransition(fromScene, overlay, replacedTransition),
+ TransitionState.HasOverscrollProperties {
+ override val isEffectivelyShown: Boolean
+ get() = isEffectivelyShown()
override val progress: Float
get() = progress()
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestTransition.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestSceneTransition.kt
similarity index 89%
rename from packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestTransition.kt
rename to packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestSceneTransition.kt
index a6a83ee..d24b895 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestTransition.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestSceneTransition.kt
@@ -24,8 +24,8 @@
import com.android.compose.animation.scene.content.state.TransitionState.Transition
import kotlinx.coroutines.CompletableDeferred
-/** A transition for tests that will be finished once [finish] is called. */
-abstract class TestTransition(
+/** A [Transition.ChangeScene] for tests that will be finished once [finish] is called. */
+abstract class TestSceneTransition(
fromScene: SceneKey,
toScene: SceneKey,
replacedTransition: Transition?,
@@ -42,7 +42,7 @@
}
}
-/** A utility to easily create a [TestTransition] in tests. */
+/** A utility to easily create a [TestSceneTransition] in tests. */
fun transition(
from: SceneKey,
to: SceneKey,
@@ -58,11 +58,11 @@
isUpOrLeft: Boolean = false,
bouncingContent: ContentKey? = null,
orientation: Orientation = Orientation.Horizontal,
- onFreezeAndAnimate: ((TestTransition) -> Unit)? = null,
+ onFreezeAndAnimate: ((TestSceneTransition) -> Unit)? = null,
replacedTransition: Transition? = null,
-): TestTransition {
+): TestSceneTransition {
return object :
- TestTransition(from, to, replacedTransition), TransitionState.HasOverscrollProperties {
+ TestSceneTransition(from, to, replacedTransition), TransitionState.HasOverscrollProperties {
override val currentScene: SceneKey
get() = current()
diff --git a/packages/SystemUI/docs/scene.md b/packages/SystemUI/docs/scene.md
index a7740c6..0ac15c5 100644
--- a/packages/SystemUI/docs/scene.md
+++ b/packages/SystemUI/docs/scene.md
@@ -124,8 +124,8 @@
[`Scene`](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Scene.kt)
interface, which has three parts: 1. The `key` property returns the
[`SceneKey`](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneKey.kt)
-that uniquely identifies that scene 2. The `destinationScenes` `Flow` returns
-the (potentially ever-changing) set of navigation edges to other scenes, based
+that uniquely identifies that scene 2. The `userActions` `Flow` returns
+the (potentially ever-changing) set of navigation edges to other content, based
on user-actions, which is how the navigation graph is defined (see
[the Scene navigation](#Scene-navigation) section for more) 3. The `Content`
function which uses
@@ -141,7 +141,7 @@
@SysUISingleton class YourScene @Inject constructor( /* your dependencies here */ ) : Scene {
override val key = SceneKey.YourScene
- override val destinationScenes: StateFlow<Map<UserAction, SceneModel>> =
+ override val userActions: StateFlow<Map<UserAction, SceneModel>> =
MutableStateFlow<Map<UserAction, SceneModel>>(
mapOf(
// This is where scene navigation is defined, more on that below.
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
index e2bdc49..bb15208 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
@@ -30,10 +30,12 @@
import com.android.systemui.classifier.FalsingCollectorFake
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
+import com.android.systemui.haptics.msdl.msdlPlayer
import com.android.systemui.res.R
import com.android.systemui.statusbar.policy.DevicePostureController
import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_HALF_OPENED
import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_OPENED
+import com.android.systemui.testKosmos
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.whenever
@@ -89,6 +91,9 @@
@Captor lateinit var postureCallbackCaptor: ArgumentCaptor<DevicePostureController.Callback>
+ private val kosmos = testKosmos()
+ private val msdlPlayer = kosmos.msdlPlayer
+
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
@@ -112,7 +117,8 @@
mKeyguardMessageAreaControllerFactory,
mPostureController,
fakeFeatureFlags,
- mSelectedUserInteractor
+ mSelectedUserInteractor,
+ msdlPlayer,
)
mKeyguardPatternView.onAttachedToWindow()
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
index 18ed22a..e444db4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
@@ -18,10 +18,8 @@
package com.android.keyguard
import android.app.admin.DevicePolicyManager
-import android.app.admin.flags.Flags as DevicePolicyFlags
import android.content.res.Configuration
import android.media.AudioManager
-import android.platform.test.annotations.EnableFlags
import android.telephony.TelephonyManager
import android.testing.TestableLooper.RunWithLooper
import android.testing.TestableResources
@@ -942,7 +940,6 @@
}
@Test
- @EnableFlags(DevicePolicyFlags.FLAG_HEADLESS_SINGLE_USER_FIXES)
fun showAlmostAtWipeDialog_calledOnMainUser_setsCorrectUserType() {
val mainUserId = 10
@@ -959,7 +956,6 @@
}
@Test
- @EnableFlags(DevicePolicyFlags.FLAG_HEADLESS_SINGLE_USER_FIXES)
fun showAlmostAtWipeDialog_calledOnNonMainUser_setsCorrectUserType() {
val secondaryUserId = 10
val mainUserId = 0
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/MirrorWindowControlTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/MirrorWindowControlTest.java
index 8f9b7c8..12c866f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/MirrorWindowControlTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/MirrorWindowControlTest.java
@@ -30,11 +30,11 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.view.WindowManager;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
import com.android.systemui.SysuiTestCase;
import org.junit.Before;
@@ -48,7 +48,7 @@
@RunWith(AndroidJUnit4.class)
public class MirrorWindowControlTest extends SysuiTestCase {
- @Mock WindowManager mWindowManager;
+ @Mock ViewCaptureAwareWindowManager mWindowManager;
View mView;
int mViewWidth;
int mViewHeight;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/view/accessibility/data/repository/CaptioningRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/data/repository/CaptioningRepositoryTest.kt
similarity index 66%
rename from packages/SettingsLib/tests/integ/src/com/android/settingslib/view/accessibility/data/repository/CaptioningRepositoryTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/data/repository/CaptioningRepositoryTest.kt
index a5233e7..fc57757 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/view/accessibility/data/repository/CaptioningRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/data/repository/CaptioningRepositoryTest.kt
@@ -14,16 +14,21 @@
* limitations under the License.
*/
-package com.android.settingslib.view.accessibility.data.repository
+package com.android.systemui.accessibility.data.repository
import android.view.accessibility.CaptioningManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectValues
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.android.systemui.user.data.repository.userRepository
+import com.android.systemui.user.utils.FakeUserScopedService
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -38,9 +43,10 @@
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@Suppress("UnspecifiedRegisterReceiverFlag")
@RunWith(AndroidJUnit4::class)
-class CaptioningRepositoryTest {
+class CaptioningRepositoryTest : SysuiTestCase() {
+
+ private val kosmos = testKosmos()
@Captor
private lateinit var listenerCaptor: ArgumentCaptor<CaptioningManager.CaptioningChangeListener>
@@ -49,34 +55,33 @@
private lateinit var underTest: CaptioningRepository
- private val testScope = TestScope()
-
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
underTest =
- CaptioningRepositoryImpl(
- captioningManager,
- testScope.testScheduler,
- testScope.backgroundScope
- )
+ with(kosmos) {
+ CaptioningRepositoryImpl(
+ FakeUserScopedService(captioningManager),
+ userRepository,
+ testScope.testScheduler,
+ applicationCoroutineScope,
+ )
+ }
}
@Test
fun isSystemAudioCaptioningEnabled_change_repositoryEmits() {
- testScope.runTest {
- `when`(captioningManager.isEnabled).thenReturn(false)
- val isSystemAudioCaptioningEnabled = mutableListOf<Boolean>()
- underTest.isSystemAudioCaptioningEnabled
- .onEach { isSystemAudioCaptioningEnabled.add(it) }
- .launchIn(backgroundScope)
+ kosmos.testScope.runTest {
+ `when`(captioningManager.isSystemAudioCaptioningEnabled).thenReturn(false)
+ val models by collectValues(underTest.captioningModel.filterNotNull())
runCurrent()
+ `when`(captioningManager.isSystemAudioCaptioningEnabled).thenReturn(true)
triggerOnSystemAudioCaptioningChange()
runCurrent()
- assertThat(isSystemAudioCaptioningEnabled)
+ assertThat(models.map { it.isSystemAudioCaptioningEnabled })
.containsExactlyElementsIn(listOf(false, true))
.inOrder()
}
@@ -84,18 +89,16 @@
@Test
fun isSystemAudioCaptioningUiEnabled_change_repositoryEmits() {
- testScope.runTest {
- `when`(captioningManager.isSystemAudioCaptioningUiEnabled).thenReturn(false)
- val isSystemAudioCaptioningUiEnabled = mutableListOf<Boolean>()
- underTest.isSystemAudioCaptioningUiEnabled
- .onEach { isSystemAudioCaptioningUiEnabled.add(it) }
- .launchIn(backgroundScope)
+ kosmos.testScope.runTest {
+ `when`(captioningManager.isEnabled).thenReturn(false)
+ val models by collectValues(underTest.captioningModel.filterNotNull())
runCurrent()
+ `when`(captioningManager.isSystemAudioCaptioningUiEnabled).thenReturn(true)
triggerSystemAudioCaptioningUiChange()
runCurrent()
- assertThat(isSystemAudioCaptioningUiEnabled)
+ assertThat(models.map { it.isSystemAudioCaptioningUiEnabled })
.containsExactlyElementsIn(listOf(false, true))
.inOrder()
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManagerTest.java
index 09aa2868..ca23228 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManagerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManagerTest.java
@@ -17,11 +17,11 @@
package com.android.systemui.accessibility.hearingaid;
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.bluetooth.BluetoothDevice;
import android.testing.TestableLooper;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -51,6 +51,8 @@
@Rule
public MockitoRule mockito = MockitoJUnit.rule();
+ private static final int TEST_LAUNCH_SOURCE_ID = 1;
+
private final FakeExecutor mMainExecutor = new FakeExecutor(new FakeSystemClock());
private final FakeExecutor mBackgroundExecutor = new FakeExecutor(new FakeSystemClock());
@Mock
@@ -70,7 +72,7 @@
@Before
public void setUp() {
- when(mDialogFactory.create(anyBoolean())).thenReturn(mDialogDelegate);
+ when(mDialogFactory.create(anyBoolean(), anyInt())).thenReturn(mDialogDelegate);
when(mDialogDelegate.createDialog()).thenReturn(mDialog);
mManager = new HearingDevicesDialogManager(
@@ -86,21 +88,22 @@
public void showDialog_existHearingDevice_showPairNewDeviceFalse() {
when(mDevicesChecker.isAnyPairedHearingDevice()).thenReturn(true);
- mManager.showDialog(mExpandable);
+ mManager.showDialog(mExpandable, TEST_LAUNCH_SOURCE_ID);
mBackgroundExecutor.runAllReady();
mMainExecutor.runAllReady();
- verify(mDialogFactory).create(eq(/* showPairNewDevice= */ false));
+ verify(mDialogFactory).create(eq(/* showPairNewDevice= */ false),
+ eq(TEST_LAUNCH_SOURCE_ID));
}
@Test
public void showDialog_noHearingDevice_showPairNewDeviceTrue() {
when(mDevicesChecker.isAnyPairedHearingDevice()).thenReturn(false);
- mManager.showDialog(mExpandable);
+ mManager.showDialog(mExpandable, TEST_LAUNCH_SOURCE_ID);
mBackgroundExecutor.runAllReady();
mMainExecutor.runAllReady();
- verify(mDialogFactory).create(eq(/* showPairNewDevice= */ true));
+ verify(mDialogFactory).create(eq(/* showPairNewDevice= */ true), eq(TEST_LAUNCH_SOURCE_ID));
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
index 1cd9d76..72163e4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
@@ -31,9 +31,7 @@
import com.android.systemui.coroutines.collectValues
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
-import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
-import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.testKosmos
import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.util.mockito.whenever
@@ -58,14 +56,13 @@
@Mock private lateinit var lockPatternUtils: LockPatternUtils
@Mock private lateinit var getSecurityMode: Function<Int, KeyguardSecurityModel.SecurityMode>
- @Mock private lateinit var tableLogger: TableLogBuffer
@Mock private lateinit var devicePolicyManager: DevicePolicyManager
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
private val clock = FakeSystemClock()
private val userRepository = FakeUserRepository()
- private lateinit var mobileConnectionsRepository: FakeMobileConnectionsRepository
+ private val mobileConnectionsRepository = kosmos.fakeMobileConnectionsRepository
private lateinit var underTest: AuthenticationRepository
@@ -78,8 +75,6 @@
userRepository.setUserInfos(USER_INFOS)
runBlocking { userRepository.setSelectedUserInfo(USER_INFOS[0]) }
whenever(getSecurityMode.apply(anyInt())).thenAnswer { currentSecurityMode }
- mobileConnectionsRepository =
- FakeMobileConnectionsRepository(FakeMobileMappingsProxy(), tableLogger)
underTest =
AuthenticationRepositoryImpl(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
index 0c5e726..080b48a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
@@ -17,8 +17,6 @@
package com.android.systemui.authentication.domain.interactor
import android.app.admin.DevicePolicyManager
-import android.app.admin.flags.Flags as DevicePolicyFlags
-import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
@@ -414,7 +412,6 @@
}
@Test
- @EnableFlags(DevicePolicyFlags.FLAG_HEADLESS_SINGLE_USER_FIXES)
fun upcomingWipe() =
testScope.runTest {
val upcomingWipe by collectLastValue(underTest.upcomingWipe)
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 b7d99d2..65825b2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -97,6 +97,8 @@
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
+import com.google.android.msdl.domain.MSDLPlayer;
+
import dagger.Lazy;
import org.junit.Before;
@@ -185,6 +187,8 @@
private Resources mResources;
@Mock
private VibratorHelper mVibratorHelper;
+ @Mock
+ private MSDLPlayer mMSDLPlayer;
private TestableContext mContextSpy;
private Execution mExecution;
@@ -1066,7 +1070,7 @@
() -> mLogContextInteractor, () -> mPromptSelectionInteractor,
() -> mCredentialViewModel, () -> mPromptViewModel, mInteractionJankMonitor,
mHandler, mBackgroundExecutor, mUdfpsUtils, mVibratorHelper,
- mLazyViewCapture);
+ mLazyViewCapture, mMSDLPlayer);
}
@Override
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt
index 65236f0..e3b5f34 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt
@@ -31,6 +31,8 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.telephony.data.repository.fakeTelephonyRepository
@@ -91,6 +93,8 @@
kosmos.fakeTelephonyRepository.setHasTelephonyRadio(true)
kosmos.telecomManager = telecomManager
+
+ kosmos.sceneInteractor.changeScene(Scenes.Bouncer, "")
}
@Test
@@ -130,6 +134,7 @@
assertThat(metricsLogger.logs.element().category)
.isEqualTo(MetricsProto.MetricsEvent.ACTION_EMERGENCY_CALL)
verify(activityTaskManager).stopSystemLockTaskMode()
+ assertThat(kosmos.sceneInteractor.currentScene.value).isEqualTo(Scenes.Lockscreen)
verify(telecomManager).showInCallScreen(eq(false))
}
@@ -156,6 +161,7 @@
assertThat(metricsLogger.logs.element().category)
.isEqualTo(MetricsProto.MetricsEvent.ACTION_EMERGENCY_CALL)
verify(activityTaskManager).stopSystemLockTaskMode()
+ assertThat(kosmos.sceneInteractor.currentScene.value).isEqualTo(Scenes.Lockscreen)
// TODO(b/25189994): Test the activity has been started once we switch to the
// ActivityStarter interface here.
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerUserActionsViewModelTest.kt
similarity index 93%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerUserActionsViewModelTest.kt
index a86a0c0..f58bbc3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerUserActionsViewModelTest.kt
@@ -44,17 +44,17 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
@EnableSceneContainer
-class BouncerSceneActionsViewModelTest : SysuiTestCase() {
+class BouncerUserActionsViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
- private lateinit var underTest: BouncerSceneActionsViewModel
+ private lateinit var underTest: BouncerUserActionsViewModel
@Before
fun setUp() {
kosmos.sceneContainerStartable.start()
- underTest = kosmos.bouncerSceneActionsViewModel
+ underTest = kosmos.bouncerUserActionsViewModel
underTest.activateIn(testScope)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
index ec8cc4d..956c129 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
@@ -34,8 +34,6 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.testing.FakeMetricsLogger;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FakeFeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -83,7 +81,6 @@
private final FalsingClassifier.Result mPassedResult = FalsingClassifier.Result.passed(1);
private final FalsingClassifier.Result mFalsedResult =
FalsingClassifier.Result.falsed(1, getClass().getSimpleName(), "");
- private final FakeFeatureFlags mFakeFeatureFlags = new FakeFeatureFlags();
@Before
public void setup() {
@@ -98,11 +95,11 @@
when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList);
when(mKeyguardStateController.isShowing()).thenReturn(true);
when(mFalsingDataProvider.isUnfolded()).thenReturn(false);
+ when(mFalsingDataProvider.isTouchScreenSource()).thenReturn(true);
mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider,
mMetricsLogger, mClassifiers, mSingleTapClassifier, mLongTapClassifier,
mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController,
- mAccessibilityManager, false, mFakeFeatureFlags);
- mFakeFeatureFlags.set(Flags.FALSING_OFF_FOR_UNFOLDED, true);
+ mAccessibilityManager, false);
}
@Test
@@ -197,6 +194,13 @@
}
@Test
+ public void testSkipNonTouchscreenDevices() {
+ assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isTrue();
+ when(mFalsingDataProvider.isTouchScreenSource()).thenReturn(false);
+ assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isFalse();
+ }
+
+ @Test
public void testTrackpadGesture() {
assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isTrue();
when(mFalsingDataProvider.isFromTrackpad()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
similarity index 81%
rename from packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
index 49c6239..df4b048 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -25,13 +26,20 @@
import static org.mockito.Mockito.when;
import android.hardware.devicestate.DeviceStateManager.FoldStateListener;
+import android.hardware.input.IInputManager;
+import android.hardware.input.InputManagerGlobal;
+import android.os.RemoteException;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
import android.util.DisplayMetrics;
+import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.systemui.Flags;
import com.android.systemui.classifier.FalsingDataProvider.GestureFinalizedListener;
import com.android.systemui.dock.DockManagerFake;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -56,11 +64,15 @@
private FoldStateListener mFoldStateListener;
private final DockManagerFake mDockManager = new DockManagerFake();
private DisplayMetrics mDisplayMetrics;
+ private IInputManager mIInputManager;
+ private InputManagerGlobal.TestSession inputManagerGlobalTestSession;
@Before
public void setup() {
super.setup();
MockitoAnnotations.initMocks(this);
+ mIInputManager = mock(IInputManager.Stub.class);
+ inputManagerGlobalTestSession = InputManagerGlobal.createTestSession(mIInputManager);
mDisplayMetrics = new DisplayMetrics();
mDisplayMetrics.xdpi = 100;
mDisplayMetrics.ydpi = 100;
@@ -73,6 +85,7 @@
public void tearDown() {
super.tearDown();
mDataProvider.onSessionEnd();
+ inputManagerGlobalTestSession.close();
}
@Test
@@ -378,6 +391,79 @@
}
@Test
+ @DisableFlags(Flags.FLAG_NON_TOUCHSCREEN_DEVICES_BYPASS_FALSING)
+ public void test_isTouchscreenSource_flagOff_alwaysTrue() {
+ assertThat(mDataProvider.isTouchScreenSource()).isTrue();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_NON_TOUCHSCREEN_DEVICES_BYPASS_FALSING)
+ public void test_isTouchscreenSource_recentEventsEmpty_true() {
+ //send no events into the data provider
+ assertThat(mDataProvider.isTouchScreenSource()).isTrue();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_NON_TOUCHSCREEN_DEVICES_BYPASS_FALSING)
+ public void test_isTouchscreenSource_latestDeviceTouchscreen_true() throws RemoteException {
+ int deviceId = 999;
+
+ InputDevice device = new InputDevice.Builder()
+ .setSources(InputDevice.SOURCE_CLASS_TRACKBALL | InputDevice.SOURCE_TOUCHSCREEN)
+ .setId(deviceId)
+ .build();
+ when(mIInputManager.getInputDeviceIds()).thenReturn(new int[]{deviceId});
+ when(mIInputManager.getInputDevice(anyInt())).thenReturn(device);
+
+ MotionEvent event = MotionEvent.obtain(1, 0, MotionEvent.ACTION_UP, 1,
+ MotionEvent.PointerProperties.createArray(1),
+ MotionEvent.PointerCoords.createArray(1), 0, 0, 1.0f, 1.0f, deviceId, 0,
+ InputDevice.SOURCE_CLASS_NONE, 0, 0, 0);
+
+ mDataProvider.onMotionEvent(event);
+ boolean result = mDataProvider.isTouchScreenSource();
+ assertThat(result).isTrue();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_NON_TOUCHSCREEN_DEVICES_BYPASS_FALSING)
+ public void test_isTouchscreenSource_latestDeviceNonTouchscreen_false() throws RemoteException {
+ int deviceId = 9999;
+
+ InputDevice device = new InputDevice.Builder()
+ .setSources(InputDevice.SOURCE_CLASS_TRACKBALL)
+ .setId(deviceId)
+ .build();
+ when(mIInputManager.getInputDeviceIds()).thenReturn(new int[]{deviceId});
+ when(mIInputManager.getInputDevice(anyInt())).thenReturn(device);
+
+ MotionEvent event = MotionEvent.obtain(1, 0, MotionEvent.ACTION_UP, 1,
+ MotionEvent.PointerProperties.createArray(1),
+ MotionEvent.PointerCoords.createArray(1), 0, 0, 1.0f, 1.0f, deviceId, 0,
+ InputDevice.SOURCE_CLASS_NONE, 0, 0, 0);
+
+ mDataProvider.onMotionEvent(event);
+ boolean result = mDataProvider.isTouchScreenSource();
+ assertThat(result).isFalse();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_NON_TOUCHSCREEN_DEVICES_BYPASS_FALSING)
+ public void test_isTouchscreenSource_latestDeviceNull_true() {
+ // Do not mock InputManager for this test
+ inputManagerGlobalTestSession.close();
+
+ int nonExistentDeviceId = 9997;
+ MotionEvent event = MotionEvent.obtain(1, 0, MotionEvent.ACTION_UP, 1,
+ MotionEvent.PointerProperties.createArray(1),
+ MotionEvent.PointerCoords.createArray(1), 0, 0, 1.0f, 1.0f, nonExistentDeviceId, 0,
+ InputDevice.SOURCE_CLASS_NONE, 0, 0, 0);
+
+ mDataProvider.onMotionEvent(event);
+ assertThat(mDataProvider.isTouchScreenSource()).isTrue();
+ }
+
+ @Test
public void test_UnfoldedState_Folded() {
FalsingDataProvider falsingDataProvider = createWithFoldCapability(true);
when(mFoldStateListener.getFolded()).thenReturn(true);
@@ -413,7 +499,7 @@
}
private FalsingDataProvider createWithFoldCapability(boolean foldable) {
- return new FalsingDataProvider(
- mDisplayMetrics, mBatteryController, mFoldStateListener, mDockManager, foldable);
+ return new FalsingDataProvider(mDisplayMetrics, mBatteryController, mFoldStateListener,
+ mDockManager, foldable);
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandlerTest.kt
index bb400f2..f06cd6a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandlerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandlerTest.kt
@@ -67,7 +67,8 @@
isAttachedToWindow = { isAttachedToWindow },
onLongPressDetected = onLongPressDetected,
onSingleTapDetected = onSingleTapDetected,
- longPressDuration = { ViewConfiguration.getLongPressTimeout().toLong() }
+ longPressDuration = { ViewConfiguration.getLongPressTimeout().toLong() },
+ allowedTouchSlop = ViewConfiguration.getTouchSlop(),
)
underTest.isLongPressHandlingEnabled = true
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
index d4a7691..71abed7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
@@ -75,7 +75,7 @@
import com.android.systemui.log.FaceAuthenticationLogger
import com.android.systemui.log.SessionTracker
import com.android.systemui.log.logcatLogBuffer
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
import com.android.systemui.power.domain.interactor.powerInteractor
@@ -90,7 +90,6 @@
import com.android.systemui.util.mockito.captureMany
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import java.io.PrintWriter
import java.io.StringWriter
@@ -199,25 +198,8 @@
fmOverride: FaceManager? = faceManager,
bypassControllerOverride: KeyguardBypassController? = bypassController
): DeviceEntryFaceAuthRepositoryImpl {
- val systemClock = FakeSystemClock()
- val faceAuthBuffer =
- TableLogBuffer(
- 10,
- "face auth",
- systemClock,
- mock(),
- testDispatcher,
- testScope.backgroundScope
- )
- val faceDetectBuffer =
- TableLogBuffer(
- 10,
- "face detect",
- systemClock,
- mock(),
- testDispatcher,
- testScope.backgroundScope
- )
+ val faceAuthBuffer = logcatTableLogBuffer(kosmos, "face auth")
+ val faceDetectBuffer = logcatTableLogBuffer(kosmos, "face detect")
return DeviceEntryFaceAuthRepositoryImpl(
mContext,
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 5e6ff73..7dd7174 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
@@ -233,7 +233,7 @@
.thenReturn(dreamOverlayComponent)
val ambientTouchComponent = mock<AmbientTouchComponent>()
- whenever(ambientTouchComponentFactory.create(any(), any()))
+ whenever(ambientTouchComponentFactory.create(any(), any(), any()))
.thenReturn(ambientTouchComponent)
whenever(ambientTouchComponent.getTouchMonitor()).thenReturn(mTouchMonitor)
@@ -1172,6 +1172,43 @@
}
@Test
+ fun testDreamActivityGesturesNotBlockedDreamEndedBeforeKeyguardStateChanged() {
+ val client = client
+
+ // Inform the overlay service of dream starting.
+ client.startDream(
+ mWindowParams,
+ mDreamOverlayCallback,
+ DREAM_COMPONENT,
+ false /*isPreview*/,
+ false /*shouldShowComplication*/
+ )
+ mMainExecutor.runAllReady()
+
+ val matcherCaptor = argumentCaptor<TaskMatcher>()
+ verify(gestureInteractor)
+ .addGestureBlockedMatcher(matcherCaptor.capture(), eq(GestureInteractor.Scope.Global))
+ val matcher = matcherCaptor.firstValue
+
+ val dreamTaskInfo = TaskInfo(mock<ComponentName>(), WindowConfiguration.ACTIVITY_TYPE_DREAM)
+ assertThat(matcher.matches(dreamTaskInfo)).isTrue()
+
+ client.endDream()
+ mMainExecutor.runAllReady()
+ clearInvocations(gestureInteractor)
+
+ val callbackCaptor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
+ verify(mKeyguardUpdateMonitor).registerCallback(callbackCaptor.capture())
+
+ // Notification shade opens.
+ callbackCaptor.value.onShadeExpandedChanged(true)
+ mMainExecutor.runAllReady()
+
+ verify(gestureInteractor)
+ .removeGestureBlockedMatcher(eq(matcher), eq(GestureInteractor.Scope.Global))
+ }
+
+ @Test
fun testComponentsRecreatedBetweenDreams() {
clearInvocations(
mDreamComplicationComponentFactory,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
index ca15eff..25c5336 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
@@ -24,8 +24,10 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.contextualeducation.GestureType
+import com.android.systemui.contextualeducation.GestureType.ALL_APPS
import com.android.systemui.contextualeducation.GestureType.BACK
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.coroutines.collectValues
import com.android.systemui.education.data.model.GestureEduModel
import com.android.systemui.education.data.repository.contextualEducationRepository
import com.android.systemui.education.data.repository.fakeEduClock
@@ -61,6 +63,8 @@
private val underTest: KeyboardTouchpadEduInteractor = kosmos.keyboardTouchpadEduInteractor
private val eduClock = kosmos.fakeEduClock
+ private val minDurationForNextEdu =
+ KeyboardTouchpadEduInteractor.minIntervalBetweenEdu + 1.seconds
@Before
fun setup() {
@@ -92,7 +96,10 @@
triggerMaxEducationSignals(BACK)
// runCurrent() to trigger 1st education
runCurrent()
+
+ eduClock.offset(minDurationForNextEdu)
triggerMaxEducationSignals(BACK)
+
assertThat(model?.educationUiType).isEqualTo(EducationUiType.Notification)
}
@@ -114,6 +121,39 @@
}
@Test
+ fun no2ndEducationBeforeMinEduIntervalReached() =
+ testScope.runTest {
+ val models by collectValues(underTest.educationTriggered)
+ triggerMaxEducationSignals(BACK)
+ runCurrent()
+
+ // Offset a duration that is less than the required education interval
+ eduClock.offset(1.seconds)
+ triggerMaxEducationSignals(BACK)
+ runCurrent()
+
+ assertThat(models.filterNotNull().size).isEqualTo(1)
+ }
+
+ @Test
+ fun noNewEducationInfoAfterMaxEducationCountReached() =
+ testScope.runTest {
+ val models by collectValues(underTest.educationTriggered)
+ // Trigger 2 educations
+ triggerMaxEducationSignals(BACK)
+ runCurrent()
+ eduClock.offset(minDurationForNextEdu)
+ triggerMaxEducationSignals(BACK)
+ runCurrent()
+
+ // Try triggering 3rd education
+ eduClock.offset(minDurationForNextEdu)
+ triggerMaxEducationSignals(BACK)
+
+ assertThat(models.filterNotNull().size).isEqualTo(2)
+ }
+
+ @Test
fun startNewUsageSessionWhen2ndSignalReceivedAfterSessionDeadline() =
testScope.runTest {
val model by
@@ -220,17 +260,19 @@
verify(kosmos.mockEduInputManager)
.registerKeyGestureEventListener(any(), listenerCaptor.capture())
- val backGestureEvent =
+ val allAppsKeyGestureEvent =
KeyGestureEvent(
/* deviceId= */ 1,
- intArrayOf(KeyEvent.KEYCODE_ESCAPE),
+ IntArray(0),
KeyEvent.META_META_ON,
- KeyGestureEvent.KEY_GESTURE_TYPE_BACK
+ KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS
)
- listenerCaptor.value.onKeyGestureEvent(backGestureEvent)
+ listenerCaptor.value.onKeyGestureEvent(allAppsKeyGestureEvent)
val model by
- collectLastValue(kosmos.contextualEducationRepository.readGestureEduModelFlow(BACK))
+ collectLastValue(
+ kosmos.contextualEducationRepository.readGestureEduModelFlow(ALL_APPS)
+ )
assertThat(model?.lastShortcutTriggeredTime).isEqualTo(eduClock.instant())
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduUiCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduUiCoordinatorTest.kt
index e075b7e..c4ac585 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduUiCoordinatorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/ui/view/ContextualEduUiCoordinatorTest.kt
@@ -25,6 +25,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.contextualeducation.GestureType
import com.android.systemui.contextualeducation.GestureType.BACK
+import com.android.systemui.education.data.repository.fakeEduClock
import com.android.systemui.education.domain.interactor.KeyboardTouchpadEduInteractor
import com.android.systemui.education.domain.interactor.contextualEducationInteractor
import com.android.systemui.education.domain.interactor.keyboardTouchpadEduInteractor
@@ -35,6 +36,7 @@
import com.android.systemui.res.R
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
+import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
@@ -56,6 +58,9 @@
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
private val interactor = kosmos.contextualEducationInteractor
+ private val eduClock = kosmos.fakeEduClock
+ private val minDurationForNextEdu =
+ KeyboardTouchpadEduInteractor.minIntervalBetweenEdu + 1.seconds
private lateinit var underTest: ContextualEduUiCoordinator
@Mock private lateinit var toast: Toast
@Mock private lateinit var notificationManager: NotificationManager
@@ -94,6 +99,7 @@
fun showNotificationOn2ndEdu() =
testScope.runTest {
triggerEducation(BACK)
+ eduClock.offset(minDurationForNextEdu)
triggerEducation(BACK)
verify(notificationManager).notifyAsUser(any(), anyInt(), any(), any())
}
@@ -110,7 +116,10 @@
testScope.runTest {
val notificationCaptor = ArgumentCaptor.forClass(Notification::class.java)
triggerEducation(BACK)
+
+ eduClock.offset(minDurationForNextEdu)
triggerEducation(BACK)
+
verify(notificationManager)
.notifyAsUser(any(), anyInt(), notificationCaptor.capture(), any())
verifyNotificationContent(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt
index fd4ed38..686b518 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt
@@ -23,7 +23,7 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ActivityTransitionAnimator
-import com.android.systemui.haptics.vibratorHelper
+import com.android.systemui.haptics.fakeVibratorHelper
import com.android.systemui.kosmos.testScope
import com.android.systemui.log.core.FakeLogBuffer
import com.android.systemui.qs.qsTileFactory
@@ -50,7 +50,7 @@
@Rule @JvmField val mMockitoRule: MockitoRule = MockitoJUnit.rule()
private val kosmos = testKosmos()
- private val vibratorHelper = kosmos.vibratorHelper
+ private val vibratorHelper = kosmos.fakeVibratorHelper
private val qsTile = kosmos.qsTileFactory.createTile("Test Tile")
@Mock private lateinit var callback: QSLongPressEffect.Callback
@Mock private lateinit var controller: ActivityTransitionAnimator.Controller
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
index c5ba02d..4e429c3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepositoryTest.kt
@@ -46,11 +46,10 @@
import com.android.systemui.keyguard.data.repository.BiometricType.SIDE_FINGERPRINT
import com.android.systemui.keyguard.data.repository.BiometricType.UNDER_DISPLAY_FINGERPRINT
import com.android.systemui.keyguard.shared.model.DevicePosture
-import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.res.R
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
-import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.statusbar.policy.DevicePostureController
+import com.android.systemui.testKosmos
import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.whenever
@@ -81,6 +80,8 @@
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@RunWith(AndroidJUnit4::class)
class BiometricSettingsRepositoryTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+
private lateinit var underTest: BiometricSettingsRepository
@Mock private lateinit var authController: AuthController
@@ -88,7 +89,6 @@
@Mock private lateinit var devicePolicyManager: DevicePolicyManager
@Mock private lateinit var dumpManager: DumpManager
@Mock private lateinit var biometricManager: BiometricManager
- @Mock private lateinit var tableLogger: TableLogBuffer
@Captor
private lateinit var strongAuthTracker: ArgumentCaptor<LockPatternUtils.StrongAuthTracker>
@Captor private lateinit var authControllerCallback: ArgumentCaptor<AuthController.Callback>
@@ -99,7 +99,7 @@
private lateinit var devicePostureRepository: FakeDevicePostureRepository
private lateinit var facePropertyRepository: FakeFacePropertyRepository
private lateinit var fingerprintPropertyRepository: FakeFingerprintPropertyRepository
- private lateinit var mobileConnectionsRepository: FakeMobileConnectionsRepository
+ private val mobileConnectionsRepository = kosmos.fakeMobileConnectionsRepository
private lateinit var testDispatcher: TestDispatcher
private lateinit var testScope: TestScope
@@ -115,8 +115,6 @@
devicePostureRepository = FakeDevicePostureRepository()
facePropertyRepository = FakeFacePropertyRepository()
fingerprintPropertyRepository = FakeFingerprintPropertyRepository()
- mobileConnectionsRepository =
- FakeMobileConnectionsRepository(FakeMobileMappingsProxy(), tableLogger)
}
private suspend fun createBiometricSettingsRepository() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractorTest.kt
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
index 8236eec..6f7e9d3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
@@ -128,8 +128,7 @@
fun areNotificationsVisible_splitShadeTrue_true() =
with(kosmos) {
testScope.runTest {
- val areNotificationsVisible by
- collectLastValue(underTest.areNotificationsVisible(Scenes.Lockscreen))
+ val areNotificationsVisible by collectLastValue(underTest.areNotificationsVisible())
shadeRepository.setShadeLayoutWide(true)
fakeKeyguardClockRepository.setClockSize(ClockSize.LARGE)
@@ -142,36 +141,7 @@
fun areNotificationsVisible_dualShadeWideOnLockscreen_true() =
with(kosmos) {
testScope.runTest {
- val areNotificationsVisible by
- collectLastValue(underTest.areNotificationsVisible(Scenes.Lockscreen))
- shadeRepository.setShadeLayoutWide(true)
- fakeKeyguardClockRepository.setClockSize(ClockSize.LARGE)
-
- assertThat(areNotificationsVisible).isTrue()
- }
- }
-
- @Test
- @EnableFlags(DualShade.FLAG_NAME)
- fun areNotificationsVisible_dualShadeWideOnNotificationsShade_false() =
- with(kosmos) {
- testScope.runTest {
- val areNotificationsVisible by
- collectLastValue(underTest.areNotificationsVisible(Scenes.NotificationsShade))
- shadeRepository.setShadeLayoutWide(true)
- fakeKeyguardClockRepository.setClockSize(ClockSize.LARGE)
-
- assertThat(areNotificationsVisible).isFalse()
- }
- }
-
- @Test
- @EnableFlags(DualShade.FLAG_NAME)
- fun areNotificationsVisible_dualShadeWideOnQuickSettingsShade_true() =
- with(kosmos) {
- testScope.runTest {
- val areNotificationsVisible by
- collectLastValue(underTest.areNotificationsVisible(Scenes.QuickSettingsShade))
+ val areNotificationsVisible by collectLastValue(underTest.areNotificationsVisible())
shadeRepository.setShadeLayoutWide(true)
fakeKeyguardClockRepository.setClockSize(ClockSize.LARGE)
@@ -184,8 +154,7 @@
fun areNotificationsVisible_withSmallClock_true() =
with(kosmos) {
testScope.runTest {
- val areNotificationsVisible by
- collectLastValue(underTest.areNotificationsVisible(Scenes.Lockscreen))
+ val areNotificationsVisible by collectLastValue(underTest.areNotificationsVisible())
fakeKeyguardClockRepository.setClockSize(ClockSize.SMALL)
assertThat(areNotificationsVisible).isTrue()
}
@@ -196,8 +165,7 @@
fun areNotificationsVisible_withLargeClock_false() =
with(kosmos) {
testScope.runTest {
- val areNotificationsVisible by
- collectLastValue(underTest.areNotificationsVisible(Scenes.Lockscreen))
+ val areNotificationsVisible by collectLastValue(underTest.areNotificationsVisible())
fakeKeyguardClockRepository.setClockSize(ClockSize.LARGE)
assertThat(areNotificationsVisible).isFalse()
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModelTest.kt
index 86b3f33..0a0ded7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModelTest.kt
@@ -34,6 +34,7 @@
import com.android.systemui.testKosmos
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
@@ -85,26 +86,22 @@
testScope.runTest {
fingerprintPropertyRepository.supportsUdfps()
biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false)
+
val values by collectValues(underTest.deviceEntryParentViewAlpha)
+ runCurrent()
keyguardTransitionRepository.sendTransitionSteps(
- listOf(
- step(0f, TransitionState.STARTED),
- step(0f),
- step(0.1f),
- step(0.2f),
- step(0.3f),
- step(1f),
- ),
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.DOZING,
testScope,
)
- values.forEach { assertThat(it).isEqualTo(0f) }
+ assertThat(values[0]).isEqualTo(1f)
+ assertThat(values[1]).isEqualTo(0f)
}
-
@Test
- fun lockscreenAlphaFadesOutAndFinishesVisible() =
+ fun lockscreenAlphaDoesNotFadeOut() =
testScope.runTest {
val alpha by collectValues(underTest.lockscreenAlpha)
keyguardTransitionRepository.sendTransitionSteps(
@@ -113,31 +110,7 @@
testScope,
)
- assertThat(alpha[0]).isEqualTo(1f)
- // Halfway through, it will have faded out
- assertThat(alpha[1]).isEqualTo(0f)
- // FINISHED alpha should be visible, to support pulsing
- assertThat(alpha[2]).isEqualTo(1f)
- }
-
- @Test
- fun deviceEntryBackgroundViewDisappear() =
- testScope.runTest {
- val values by collectValues(underTest.deviceEntryBackgroundViewAlpha)
-
- keyguardTransitionRepository.sendTransitionSteps(
- listOf(
- step(0f, TransitionState.STARTED),
- step(0f),
- step(0.1f),
- step(0.2f),
- step(0.3f),
- step(1f),
- ),
- testScope,
- )
-
- values.forEach { assertThat(it).isEqualTo(0f) }
+ alpha.forEach { assertThat(it).isEqualTo(1f) }
}
private fun step(value: Float, state: TransitionState = RUNNING): TransitionStep {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
similarity index 91%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneActionsViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
index c66ebf3..4253c29 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
@@ -63,7 +63,7 @@
@RunWith(ParameterizedAndroidJunit4::class)
@RunWithLooper
@EnableSceneContainer
-class LockscreenSceneActionsViewModelTest : SysuiTestCase() {
+class LockscreenUserActionsViewModelTest : SysuiTestCase() {
companion object {
private const val parameterCount = 6
@@ -170,7 +170,7 @@
@Test
@EnableFlags(Flags.FLAG_COMMUNAL_HUB)
- fun destinationScenes() =
+ fun userActions() =
testScope.runTest {
underTest.activateIn(this)
kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true)
@@ -193,9 +193,9 @@
},
)
- val destinationScenes by collectLastValue(underTest.actions)
+ val userActions by collectLastValue(underTest.actions)
val downDestination =
- destinationScenes?.get(
+ userActions?.get(
Swipe(
SwipeDirection.Down,
fromSource = Edge.Top.takeIf { downFromEdge },
@@ -227,11 +227,10 @@
val upScene by
collectLastValue(
- (destinationScenes?.get(Swipe(SwipeDirection.Up))
- as? UserActionResult.ChangeScene)
- ?.toScene
- ?.let { scene -> kosmos.sceneInteractor.resolveSceneFamily(scene) }
- ?: flowOf(null)
+ (userActions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene?.let {
+ scene ->
+ kosmos.sceneInteractor.resolveSceneFamily(scene)
+ } ?: flowOf(null)
)
assertThat(upScene)
@@ -244,11 +243,10 @@
val leftScene by
collectLastValue(
- (destinationScenes?.get(Swipe(SwipeDirection.Left))
- as? UserActionResult.ChangeScene)
- ?.toScene
- ?.let { scene -> kosmos.sceneInteractor.resolveSceneFamily(scene) }
- ?: flowOf(null)
+ (userActions?.get(Swipe.Left) as? UserActionResult.ChangeScene)?.toScene?.let {
+ scene ->
+ kosmos.sceneInteractor.resolveSceneFamily(scene)
+ } ?: flowOf(null)
)
assertThat(leftScene)
@@ -260,8 +258,8 @@
)
}
- private fun createLockscreenSceneViewModel(): LockscreenSceneActionsViewModel {
- return LockscreenSceneActionsViewModel(
+ private fun createLockscreenSceneViewModel(): LockscreenUserActionsViewModel {
+ return LockscreenUserActionsViewModel(
deviceEntryInteractor = kosmos.deviceEntryInteractor,
communalInteractor = kosmos.communalInteractor,
shadeInteractor = kosmos.shadeInteractor,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt
index 22e5896..69ccc58 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt
@@ -34,7 +34,6 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.Flags.MEDIA_RESUME_PROGRESS
-import com.android.systemui.flags.Flags.MEDIA_SESSION_ACTIONS
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.graphics.imageLoader
import com.android.systemui.kosmos.testDispatcher
@@ -42,7 +41,6 @@
import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.media.controls.util.fakeMediaControllerFactory
import com.android.systemui.media.controls.util.mediaFlags
-import com.android.systemui.plugins.activityStarter
import com.android.systemui.res.R
import com.android.systemui.statusbar.SbnBuilder
import com.android.systemui.testKosmos
@@ -87,7 +85,6 @@
context,
testDispatcher,
testScope,
- kosmos.activityStarter,
mediaControllerFactory,
mediaFlags,
kosmos.imageLoader,
@@ -96,7 +93,6 @@
@Before
fun setUp() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
mediaControllerFactory.setControllerForToken(session.sessionToken, mediaController)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModelTest.kt
similarity index 97%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneActionsViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModelTest.kt
index ed7f96fb..46b02e92 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModelTest.kt
@@ -37,7 +37,7 @@
import com.android.systemui.scene.domain.resolver.homeSceneFamilyResolver
import com.android.systemui.scene.shared.model.SceneFamilies
import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.shade.ui.viewmodel.notificationsShadeSceneActionsViewModel
+import com.android.systemui.shade.ui.viewmodel.notificationsShadeUserActionsViewModel
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -52,14 +52,14 @@
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@EnableSceneContainer
-class NotificationsShadeSceneActionsViewModelTest : SysuiTestCase() {
+class NotificationsShadeUserActionsViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
private val sceneInteractor by lazy { kosmos.sceneInteractor }
private val deviceUnlockedInteractor by lazy { kosmos.deviceUnlockedInteractor }
- private val underTest by lazy { kosmos.notificationsShadeSceneActionsViewModel }
+ private val underTest by lazy { kosmos.notificationsShadeUserActionsViewModel }
@Test
fun upTransitionSceneKey_deviceLocked_lockscreen() =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/airplane/domain/interactor/AirplaneModeTileUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/airplane/domain/interactor/AirplaneModeTileUserActionInteractorTest.kt
index 79fcc92..d27e810 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/airplane/domain/interactor/AirplaneModeTileUserActionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/airplane/domain/interactor/AirplaneModeTileUserActionInteractorTest.kt
@@ -29,8 +29,9 @@
import com.android.systemui.qs.tiles.impl.airplane.domain.model.AirplaneModeTileModel
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
+import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
import org.junit.Test
@@ -40,8 +41,9 @@
@EnabledOnRavenwood
@RunWith(AndroidJUnit4::class)
class AirplaneModeTileUserActionInteractorTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
- private val mobileConnectionsRepository = FakeMobileConnectionsRepository()
+ private val mobileConnectionsRepository = kosmos.fakeMobileConnectionsRepository
private val connectivityRepository = FakeConnectivityRepository()
private val airplaneModeRepository = FakeAirplaneModeRepository()
private val inputHandler = FakeQSTileIntentUserInputHandler()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractorTest.kt
index 1ea8abc..aaad0fc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractorTest.kt
@@ -33,7 +33,7 @@
import com.android.systemui.flags.Flags
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
import com.android.systemui.qs.tiles.impl.internet.domain.model.InternetTileModel
import com.android.systemui.res.R
@@ -86,7 +86,7 @@
private val wifiInteractor =
WifiInteractorImpl(connectivityRepository, wifiRepository, testScope.backgroundScope)
- private val tableLogBuffer: TableLogBuffer = mock()
+ private val tableLogBuffer = logcatTableLogBuffer(kosmos, "InternetTileDataInteractorTest")
private val carrierConfigTracker: CarrierConfigTracker = mock()
private val mobileConnectionsRepository =
@@ -185,7 +185,6 @@
val networkModel =
WifiNetworkModel.Active(
- networkId = 1,
level = 4,
ssid = "test ssid",
)
@@ -221,7 +220,6 @@
val networkModel =
WifiNetworkModel.Active(
- networkId = 1,
level = 4,
ssid = "test ssid",
hotspotDeviceType = WifiNetworkModel.HotspotDeviceType.NONE,
@@ -546,7 +544,6 @@
private fun setWifiNetworkWithHotspot(hotspot: WifiNetworkModel.HotspotDeviceType) {
val networkModel =
WifiNetworkModel.Active(
- networkId = 1,
level = 4,
ssid = "test ssid",
hotspotDeviceType = hotspot,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractorTest.kt
index 4e58069..5bd3645 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractorTest.kt
@@ -31,6 +31,7 @@
import com.android.systemui.qs.tiles.base.interactor.QSTileInput
import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
import com.android.systemui.recordissue.RecordIssueDialogDelegate
+import com.android.systemui.screenrecord.RecordingController
import com.android.systemui.settings.UserContextProvider
import com.android.systemui.settings.userTracker
import com.android.systemui.statusbar.phone.KeyguardDismissUtil
@@ -40,12 +41,16 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.Mock
import org.mockito.Mockito.mock
+import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(AndroidJUnit4::class)
class IssueRecordingUserActionInteractorTest : SysuiTestCase() {
+ @Mock private lateinit var recordingController: RecordingController
+
val user = UserHandle(1)
val kosmos = Kosmos().also { it.testCase = this }
@@ -56,6 +61,7 @@
@Before
fun setup() {
+ MockitoAnnotations.initMocks(this)
hasCreatedDialogDelegate = false
with(kosmos) {
val factory =
@@ -84,7 +90,8 @@
dialogTransitionAnimator,
panelInteractor,
userTracker,
- factory
+ factory,
+ recordingController,
)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt
index 91d8e2a..de3dc57 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt
@@ -25,7 +25,9 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.R
+import com.android.settingslib.notification.modes.TestModeBuilder
import com.android.systemui.SysuiTestCase
+import com.android.systemui.SysuiTestableContext
import com.android.systemui.common.shared.model.asIcon
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
@@ -62,7 +64,12 @@
context.orCreateTestableResources.apply {
addOverride(MODES_DRAWABLE_ID, MODES_DRAWABLE)
addOverride(R.drawable.ic_zen_mode_type_bedtime, BEDTIME_DRAWABLE)
- addOverride(R.drawable.ic_zen_mode_type_driving, DRIVING_DRAWABLE)
+ }
+
+ val customPackageContext = SysuiTestableContext(context)
+ context.prepareCreatePackageContext(CUSTOM_PACKAGE, customPackageContext)
+ customPackageContext.orCreateTestableResources.apply {
+ addOverride(CUSTOM_DRAWABLE_ID, CUSTOM_DRAWABLE)
}
}
@@ -146,35 +153,41 @@
assertThat(tileData?.icon).isEqualTo(MODES_ICON)
assertThat(tileData?.iconResId).isEqualTo(MODES_DRAWABLE_ID)
- // Add an active mode: icon should be the mode icon. No iconResId, because we don't
- // really know that it's a system icon.
+ // Add an active mode with a default icon: icon should be the mode icon, and the
+ // iconResId is also populated, because we know it's a system icon.
zenModeRepository.addMode(
- id = "Bedtime",
+ id = "Bedtime with default icon",
type = AutomaticZenRule.TYPE_BEDTIME,
active = true
)
runCurrent()
assertThat(tileData?.icon).isEqualTo(BEDTIME_ICON)
- assertThat(tileData?.iconResId).isNull()
+ assertThat(tileData?.iconResId).isEqualTo(R.drawable.ic_zen_mode_type_bedtime)
- // Add another, less-prioritized mode: icon should remain the first mode icon
+ // Add another, less-prioritized mode that has a *custom* icon: for now, icon should
+ // remain the first mode icon
zenModeRepository.addMode(
- id = "Driving",
- type = AutomaticZenRule.TYPE_DRIVING,
- active = true
+ TestModeBuilder()
+ .setId("Driving with custom icon")
+ .setType(AutomaticZenRule.TYPE_DRIVING)
+ .setPackage(CUSTOM_PACKAGE)
+ .setIconResId(CUSTOM_DRAWABLE_ID)
+ .setActive(true)
+ .build()
)
runCurrent()
assertThat(tileData?.icon).isEqualTo(BEDTIME_ICON)
- assertThat(tileData?.iconResId).isNull()
+ assertThat(tileData?.iconResId).isEqualTo(R.drawable.ic_zen_mode_type_bedtime)
// Deactivate more important mode: icon should be the less important, still active mode
- zenModeRepository.deactivateMode("Bedtime")
+ // And because it's a package-provided icon, iconResId is not populated.
+ zenModeRepository.deactivateMode("Bedtime with default icon")
runCurrent()
- assertThat(tileData?.icon).isEqualTo(DRIVING_ICON)
+ assertThat(tileData?.icon).isEqualTo(CUSTOM_ICON)
assertThat(tileData?.iconResId).isNull()
// Deactivate remaining mode: back to the default modes icon
- zenModeRepository.deactivateMode("Driving")
+ zenModeRepository.deactivateMode("Driving with custom icon")
runCurrent()
assertThat(tileData?.icon).isEqualTo(MODES_ICON)
assertThat(tileData?.iconResId).isEqualTo(MODES_DRAWABLE_ID)
@@ -241,15 +254,17 @@
private companion object {
val TEST_USER = UserHandle.of(1)!!
+ const val CUSTOM_PACKAGE = "com.some.mode.owner.package"
val MODES_DRAWABLE_ID = R.drawable.ic_zen_priority_modes
+ const val CUSTOM_DRAWABLE_ID = 12345
val MODES_DRAWABLE = TestStubDrawable("modes_icon")
val BEDTIME_DRAWABLE = TestStubDrawable("bedtime")
- val DRIVING_DRAWABLE = TestStubDrawable("driving")
+ val CUSTOM_DRAWABLE = TestStubDrawable("custom")
val MODES_ICON = MODES_DRAWABLE.asIcon()
val BEDTIME_ICON = BEDTIME_DRAWABLE.asIcon()
- val DRIVING_ICON = DRIVING_DRAWABLE.asIcon()
+ val CUSTOM_ICON = CUSTOM_DRAWABLE.asIcon()
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapperTest.kt
index f7bdcb8..c3d45db 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapperTest.kt
@@ -18,7 +18,6 @@
import android.app.Flags
import android.graphics.drawable.TestStubDrawable
-import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -109,26 +108,7 @@
}
@Test
- @EnableFlags(Flags.FLAG_MODES_UI_ICONS)
- fun state_withEnabledFlag_noIconResId() {
- val icon = TestStubDrawable("res123").asIcon()
- val model =
- ModesTileModel(
- isActivated = false,
- activeModes = emptyList(),
- icon = icon,
- iconResId = 123 // Should not be populated, but is ignored even if present
- )
-
- val state = underTest.map(config, model)
-
- assertThat(state.icon()).isEqualTo(icon)
- assertThat(state.iconRes).isNull()
- }
-
- @Test
- @DisableFlags(Flags.FLAG_MODES_UI_ICONS)
- fun state_withDisabledFlag_includesIconResId() {
+ fun state_modelHasIconResId_includesIconResId() {
val icon = TestStubDrawable("res123").asIcon()
val model =
ModesTileModel(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModelTest.kt
similarity index 97%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModelTest.kt
index ba527d7..32772d2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModelTest.kt
@@ -53,14 +53,14 @@
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@EnableSceneContainer
-class QuickSettingsShadeSceneActionsViewModelTest : SysuiTestCase() {
+class QuickSettingsShadeUserActionsViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
private val sceneInteractor = kosmos.sceneInteractor
private val deviceUnlockedInteractor = kosmos.deviceUnlockedInteractor
- private val underTest by lazy { kosmos.quickSettingsShadeSceneActionsViewModel }
+ private val underTest by lazy { kosmos.quickSettingsShadeUserActionsViewModel }
@Test
fun upTransitionSceneKey_deviceLocked_lockscreen() =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModelTest.kt
similarity index 98%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModelTest.kt
index f26a9db..6986cf8e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModelTest.kt
@@ -57,7 +57,7 @@
@RunWith(AndroidJUnit4::class)
@RunWithLooper
@EnableSceneContainer
-class QuickSettingsSceneActionsViewModelTest : SysuiTestCase() {
+class QuickSettingsUserActionsViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
@@ -67,7 +67,7 @@
private val sceneBackInteractor = kosmos.sceneBackInteractor
private val sceneContainerStartable = kosmos.sceneContainerStartable
- private lateinit var underTest: QuickSettingsSceneActionsViewModel
+ private lateinit var underTest: QuickSettingsUserActionsViewModel
@Before
fun setUp() {
@@ -75,7 +75,7 @@
sceneContainerStartable.start()
underTest =
- QuickSettingsSceneActionsViewModel(
+ QuickSettingsUserActionsViewModel(
qsSceneAdapter = qsFlexiglassAdapter,
sceneBackInteractor = sceneBackInteractor,
)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index f365afb..2d42c42 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -18,7 +18,6 @@
package com.android.systemui.scene
-import android.telecom.TelecomManager
import android.telephony.TelephonyManager
import android.testing.TestableLooper.RunWithLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -28,54 +27,43 @@
import com.android.compose.animation.scene.Swipe
import com.android.compose.animation.scene.UserActionResult
import com.android.internal.R
-import com.android.internal.util.EmergencyAffordanceManager
import com.android.internal.util.emergencyAffordanceManager
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
import com.android.systemui.authentication.domain.interactor.authenticationInteractor
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
-import com.android.systemui.bouncer.domain.interactor.BouncerActionButtonInteractor
-import com.android.systemui.bouncer.domain.interactor.bouncerActionButtonInteractor
-import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel
import com.android.systemui.bouncer.ui.viewmodel.PasswordBouncerViewModel
import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel
import com.android.systemui.bouncer.ui.viewmodel.bouncerSceneContentViewModel
-import com.android.systemui.classifier.domain.interactor.falsingInteractor
-import com.android.systemui.communal.domain.interactor.communalInteractor
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.flags.Flags
import com.android.systemui.flags.fakeFeatureFlagsClassic
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenSceneActionsViewModel
+import com.android.systemui.keyguard.ui.viewmodel.lockscreenUserActionsViewModel
+import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
import com.android.systemui.lifecycle.activateIn
import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
import com.android.systemui.power.domain.interactor.powerInteractor
-import com.android.systemui.qs.ui.adapter.fakeQSSceneAdapter
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.domain.resolver.homeSceneFamilyResolver
import com.android.systemui.scene.domain.startable.sceneContainerStartable
-import com.android.systemui.scene.shared.logger.sceneLogger
import com.android.systemui.scene.shared.model.SceneFamilies
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
-import com.android.systemui.shade.domain.interactor.shadeInteractor
-import com.android.systemui.shade.ui.viewmodel.ShadeSceneActionsViewModel
-import com.android.systemui.shade.ui.viewmodel.ShadeSceneContentViewModel
-import com.android.systemui.shade.ui.viewmodel.shadeSceneActionsViewModel
import com.android.systemui.shade.ui.viewmodel.shadeSceneContentViewModel
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.shade.ui.viewmodel.shadeUserActionsViewModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.telephony.data.repository.fakeTelephonyRepository
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.whenever
-import com.android.telecom.telecomManager
+import com.android.telecom.mockTelecomManager
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -83,14 +71,12 @@
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.launch
-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 org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
/**
* Integration test cases for the Scene Framework.
@@ -116,195 +102,131 @@
@RunWithLooper
@EnableSceneContainer
class SceneFrameworkIntegrationTest : SysuiTestCase() {
-
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
- private val sceneContainerConfig by lazy { kosmos.sceneContainerConfig }
- private val sceneInteractor by lazy { kosmos.sceneInteractor }
- private val authenticationInteractor by lazy { kosmos.authenticationInteractor }
- private val deviceEntryInteractor by lazy { kosmos.deviceEntryInteractor }
- private val communalInteractor by lazy { kosmos.communalInteractor }
-
- private val transitionState by lazy {
- MutableStateFlow<ObservableTransitionState>(
- ObservableTransitionState.Idle(sceneContainerConfig.initialSceneKey)
- )
- }
- private val sceneContainerViewModel by lazy {
- SceneContainerViewModel(
- sceneInteractor = sceneInteractor,
- falsingInteractor = kosmos.falsingInteractor,
- powerInteractor = kosmos.powerInteractor,
- logger = kosmos.sceneLogger,
- motionEventHandlerReceiver = {},
- )
- .apply { setTransitionState(transitionState) }
- }
-
- private lateinit var mobileConnectionsRepository: FakeMobileConnectionsRepository
- private lateinit var bouncerActionButtonInteractor: BouncerActionButtonInteractor
- private lateinit var bouncerSceneContentViewModel: BouncerSceneContentViewModel
-
- private val lockscreenSceneActionsViewModel by lazy {
- LockscreenSceneActionsViewModel(
- deviceEntryInteractor = deviceEntryInteractor,
- communalInteractor = communalInteractor,
- shadeInteractor = kosmos.shadeInteractor,
- )
- }
-
- private lateinit var shadeSceneContentViewModel: ShadeSceneContentViewModel
- private lateinit var shadeSceneActionsViewModel: ShadeSceneActionsViewModel
-
- private val powerInteractor by lazy { kosmos.powerInteractor }
-
private var bouncerSceneJob: Job? = null
- private val qsFlexiglassAdapter = kosmos.fakeQSSceneAdapter
-
- private lateinit var emergencyAffordanceManager: EmergencyAffordanceManager
- private lateinit var telecomManager: TelecomManager
- private val fakeSceneDataSource = kosmos.fakeSceneDataSource
-
@Before
- fun setUp() {
- MockitoAnnotations.initMocks(this)
+ fun setUp() =
+ kosmos.run {
+ overrideResource(R.bool.config_enable_emergency_call_while_sim_locked, true)
+ whenever(mockTelecomManager.isInCall).thenReturn(false)
+ whenever(emergencyAffordanceManager.needsEmergencyAffordance()).thenReturn(true)
- overrideResource(R.bool.config_enable_emergency_call_while_sim_locked, true)
- telecomManager = checkNotNull(kosmos.telecomManager)
- whenever(telecomManager.isInCall).thenReturn(false)
- emergencyAffordanceManager = kosmos.emergencyAffordanceManager
- whenever(emergencyAffordanceManager.needsEmergencyAffordance()).thenReturn(true)
+ fakeFeatureFlagsClassic.apply { set(Flags.NEW_NETWORK_SLICE_UI, false) }
- kosmos.fakeFeatureFlagsClassic.apply { set(Flags.NEW_NETWORK_SLICE_UI, false) }
+ fakeMobileConnectionsRepository.isAnySimSecure.value = false
- mobileConnectionsRepository = kosmos.fakeMobileConnectionsRepository
- mobileConnectionsRepository.isAnySimSecure.value = false
+ fakeTelephonyRepository.apply {
+ setHasTelephonyRadio(true)
+ setCallState(TelephonyManager.CALL_STATE_IDLE)
+ setIsInCall(false)
+ }
- kosmos.fakeTelephonyRepository.apply {
- setHasTelephonyRadio(true)
- setCallState(TelephonyManager.CALL_STATE_IDLE)
- setIsInCall(false)
+ sceneContainerStartable.start()
+
+ lockscreenUserActionsViewModel.activateIn(testScope)
+ shadeSceneContentViewModel.activateIn(testScope)
+ shadeUserActionsViewModel.activateIn(testScope)
+ bouncerSceneContentViewModel.activateIn(testScope)
+ sceneContainerViewModel.activateIn(testScope)
+
+ assertWithMessage("Initial scene key mismatch!")
+ .that(sceneContainerViewModel.currentScene.value)
+ .isEqualTo(sceneContainerConfig.initialSceneKey)
+ assertWithMessage("Initial scene container visibility mismatch!")
+ .that(sceneContainerViewModel.isVisible)
+ .isTrue()
}
- bouncerActionButtonInteractor = kosmos.bouncerActionButtonInteractor
- bouncerSceneContentViewModel = kosmos.bouncerSceneContentViewModel
-
- shadeSceneContentViewModel = kosmos.shadeSceneContentViewModel
- shadeSceneActionsViewModel = kosmos.shadeSceneActionsViewModel
-
- val startable = kosmos.sceneContainerStartable
- startable.start()
-
- lockscreenSceneActionsViewModel.activateIn(testScope)
- shadeSceneContentViewModel.activateIn(testScope)
- shadeSceneActionsViewModel.activateIn(testScope)
- bouncerSceneContentViewModel.activateIn(testScope)
- sceneContainerViewModel.activateIn(testScope)
-
- assertWithMessage("Initial scene key mismatch!")
- .that(sceneContainerViewModel.currentScene.value)
- .isEqualTo(sceneContainerConfig.initialSceneKey)
- assertWithMessage("Initial scene container visibility mismatch!")
- .that(sceneContainerViewModel.isVisible)
- .isTrue()
- }
-
@Test
- fun startsInLockscreenScene() = testScope.runTest { assertCurrentScene(Scenes.Lockscreen) }
+ fun startsInLockscreenScene() =
+ testScope.runTest { kosmos.assertCurrentScene(Scenes.Lockscreen) }
@Test
fun clickLockButtonAndEnterCorrectPin_unlocksDevice() =
testScope.runTest {
- emulateUserDrivenTransition(Scenes.Bouncer)
+ kosmos.emulateUserDrivenTransition(Scenes.Bouncer)
- fakeSceneDataSource.pause()
- enterPin()
- emulatePendingTransitionProgress(
- expectedVisible = false,
- )
- assertCurrentScene(Scenes.Gone)
+ kosmos.fakeSceneDataSource.pause()
+ kosmos.enterPin()
+ kosmos.emulatePendingTransitionProgress(expectedVisible = false)
+ kosmos.assertCurrentScene(Scenes.Gone)
}
@Test
fun swipeUpOnLockscreen_enterCorrectPin_unlocksDevice() =
testScope.runTest {
- val actions by collectLastValue(lockscreenSceneActionsViewModel.actions)
+ val actions by collectLastValue(kosmos.lockscreenUserActionsViewModel.actions)
val upDestinationSceneKey =
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
- emulateUserDrivenTransition(
+ kosmos.emulateUserDrivenTransition(
to = upDestinationSceneKey,
)
- fakeSceneDataSource.pause()
- enterPin()
- emulatePendingTransitionProgress(
- expectedVisible = false,
- )
- assertCurrentScene(Scenes.Gone)
+ kosmos.fakeSceneDataSource.pause()
+ kosmos.enterPin()
+ kosmos.emulatePendingTransitionProgress(expectedVisible = false)
+ kosmos.assertCurrentScene(Scenes.Gone)
}
@Test
fun swipeUpOnLockscreen_withAuthMethodSwipe_dismissesLockscreen() =
testScope.runTest {
- setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
+ kosmos.setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
- val actions by collectLastValue(lockscreenSceneActionsViewModel.actions)
+ val actions by collectLastValue(kosmos.lockscreenUserActionsViewModel.actions)
val upDestinationSceneKey =
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(Scenes.Gone)
- emulateUserDrivenTransition(
- to = upDestinationSceneKey,
- )
+ kosmos.emulateUserDrivenTransition(to = upDestinationSceneKey)
}
@Test
fun swipeUpOnShadeScene_withAuthMethodSwipe_lockscreenNotDismissed_goesToLockscreen() =
testScope.runTest {
- val actions by collectLastValue(shadeSceneActionsViewModel.actions)
+ val actions by collectLastValue(kosmos.shadeUserActionsViewModel.actions)
val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
- setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
- assertCurrentScene(Scenes.Lockscreen)
+ kosmos.setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
+ kosmos.assertCurrentScene(Scenes.Lockscreen)
// Emulate a user swipe to the shade scene.
- emulateUserDrivenTransition(to = Scenes.Shade)
- assertCurrentScene(Scenes.Shade)
+ kosmos.emulateUserDrivenTransition(to = Scenes.Shade)
+ kosmos.assertCurrentScene(Scenes.Shade)
val upDestinationSceneKey =
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(SceneFamilies.Home)
assertThat(homeScene).isEqualTo(Scenes.Lockscreen)
- emulateUserDrivenTransition(
- to = homeScene,
- )
+ kosmos.emulateUserDrivenTransition(to = homeScene)
}
@Test
fun swipeUpOnShadeScene_withAuthMethodSwipe_lockscreenDismissed_goesToGone() =
testScope.runTest {
- val actions by collectLastValue(shadeSceneActionsViewModel.actions)
- val canSwipeToEnter by collectLastValue(deviceEntryInteractor.canSwipeToEnter)
+ val actions by collectLastValue(kosmos.shadeUserActionsViewModel.actions)
+ val canSwipeToEnter by collectLastValue(kosmos.deviceEntryInteractor.canSwipeToEnter)
val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
- setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
+ kosmos.setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
assertThat(canSwipeToEnter).isTrue()
- assertCurrentScene(Scenes.Lockscreen)
+ kosmos.assertCurrentScene(Scenes.Lockscreen)
// Emulate a user swipe to dismiss the lockscreen.
- emulateUserDrivenTransition(to = Scenes.Gone)
- assertCurrentScene(Scenes.Gone)
+ kosmos.emulateUserDrivenTransition(to = Scenes.Gone)
+ kosmos.assertCurrentScene(Scenes.Gone)
// Emulate a user swipe to the shade scene.
- emulateUserDrivenTransition(to = Scenes.Shade)
- assertCurrentScene(Scenes.Shade)
+ kosmos.emulateUserDrivenTransition(to = Scenes.Shade)
+ kosmos.assertCurrentScene(Scenes.Shade)
val upDestinationSceneKey =
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(SceneFamilies.Home)
assertThat(homeScene).isEqualTo(Scenes.Gone)
- emulateUserDrivenTransition(
+ kosmos.emulateUserDrivenTransition(
to = homeScene,
)
}
@@ -312,64 +234,64 @@
@Test
fun withAuthMethodNone_deviceWakeUp_skipsLockscreen() =
testScope.runTest {
- setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = false)
- putDeviceToSleep(instantlyLockDevice = false)
- assertCurrentScene(Scenes.Lockscreen)
+ kosmos.setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = false)
+ kosmos.putDeviceToSleep(instantlyLockDevice = false)
+ kosmos.assertCurrentScene(Scenes.Lockscreen)
- wakeUpDevice()
- assertCurrentScene(Scenes.Gone)
+ kosmos.wakeUpDevice()
+ kosmos.assertCurrentScene(Scenes.Gone)
}
@Test
fun withAuthMethodSwipe_deviceWakeUp_doesNotSkipLockscreen() =
testScope.runTest {
- setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
- putDeviceToSleep(instantlyLockDevice = false)
- assertCurrentScene(Scenes.Lockscreen)
+ kosmos.setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
+ kosmos.putDeviceToSleep(instantlyLockDevice = false)
+ kosmos.assertCurrentScene(Scenes.Lockscreen)
- wakeUpDevice()
- assertCurrentScene(Scenes.Lockscreen)
+ kosmos.wakeUpDevice()
+ kosmos.assertCurrentScene(Scenes.Lockscreen)
}
@Test
fun lockDeviceLocksDevice() =
testScope.runTest {
- unlockDevice()
- assertCurrentScene(Scenes.Gone)
+ kosmos.unlockDevice()
+ kosmos.assertCurrentScene(Scenes.Gone)
- lockDevice()
- assertCurrentScene(Scenes.Lockscreen)
+ kosmos.lockDevice()
+ kosmos.assertCurrentScene(Scenes.Lockscreen)
}
@Test
fun deviceGoesToSleep_switchesToLockscreen() =
testScope.runTest {
- unlockDevice()
- assertCurrentScene(Scenes.Gone)
+ kosmos.unlockDevice()
+ kosmos.assertCurrentScene(Scenes.Gone)
- putDeviceToSleep()
- assertCurrentScene(Scenes.Lockscreen)
+ kosmos.putDeviceToSleep()
+ kosmos.assertCurrentScene(Scenes.Lockscreen)
}
@Test
fun deviceGoesToSleep_wakeUp_unlock() =
testScope.runTest {
- unlockDevice()
- assertCurrentScene(Scenes.Gone)
- putDeviceToSleep()
- assertCurrentScene(Scenes.Lockscreen)
- wakeUpDevice()
- assertCurrentScene(Scenes.Lockscreen)
+ kosmos.unlockDevice()
+ kosmos.assertCurrentScene(Scenes.Gone)
+ kosmos.putDeviceToSleep()
+ kosmos.assertCurrentScene(Scenes.Lockscreen)
+ kosmos.wakeUpDevice()
+ kosmos.assertCurrentScene(Scenes.Lockscreen)
- unlockDevice()
- assertCurrentScene(Scenes.Gone)
+ kosmos.unlockDevice()
+ kosmos.assertCurrentScene(Scenes.Gone)
}
@Test
fun swipeUpOnLockscreenWhileUnlocked_dismissesLockscreen() =
testScope.runTest {
- unlockDevice()
- val actions by collectLastValue(lockscreenSceneActionsViewModel.actions)
+ kosmos.unlockDevice()
+ val actions by collectLastValue(kosmos.lockscreenUserActionsViewModel.actions)
val upDestinationSceneKey =
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(Scenes.Gone)
@@ -378,46 +300,47 @@
@Test
fun deviceGoesToSleep_withLockTimeout_staysOnLockscreen() =
testScope.runTest {
- unlockDevice()
- assertCurrentScene(Scenes.Gone)
- putDeviceToSleep(instantlyLockDevice = false)
- assertCurrentScene(Scenes.Lockscreen)
+ kosmos.unlockDevice()
+ kosmos.assertCurrentScene(Scenes.Gone)
+ kosmos.putDeviceToSleep(instantlyLockDevice = false)
+ kosmos.assertCurrentScene(Scenes.Lockscreen)
// Pretend like the timeout elapsed and now lock the device.
- lockDevice()
- assertCurrentScene(Scenes.Lockscreen)
+ kosmos.lockDevice()
+ kosmos.assertCurrentScene(Scenes.Lockscreen)
}
@Test
fun dismissingIme_whileOnPasswordBouncer_navigatesToLockscreen() =
testScope.runTest {
- setAuthMethod(AuthenticationMethodModel.Password)
- val actions by collectLastValue(lockscreenSceneActionsViewModel.actions)
+ kosmos.setAuthMethod(AuthenticationMethodModel.Password)
+ val actions by collectLastValue(kosmos.lockscreenUserActionsViewModel.actions)
val upDestinationSceneKey =
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
- emulateUserDrivenTransition(
+ kosmos.emulateUserDrivenTransition(
to = upDestinationSceneKey,
)
- fakeSceneDataSource.pause()
- dismissIme()
+ kosmos.fakeSceneDataSource.pause()
+ kosmos.dismissIme()
- emulatePendingTransitionProgress()
- assertCurrentScene(Scenes.Lockscreen)
+ kosmos.emulatePendingTransitionProgress()
+ kosmos.assertCurrentScene(Scenes.Lockscreen)
}
@Test
fun bouncerActionButtonClick_opensEmergencyServicesDialer() =
testScope.runTest {
- setAuthMethod(AuthenticationMethodModel.Password)
- val actions by collectLastValue(lockscreenSceneActionsViewModel.actions)
+ kosmos.setAuthMethod(AuthenticationMethodModel.Password)
+ val actions by collectLastValue(kosmos.lockscreenUserActionsViewModel.actions)
val upDestinationSceneKey =
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
- emulateUserDrivenTransition(to = upDestinationSceneKey)
+ kosmos.emulateUserDrivenTransition(to = upDestinationSceneKey)
- val bouncerActionButton by collectLastValue(bouncerSceneContentViewModel.actionButton)
+ val bouncerActionButton by
+ collectLastValue(kosmos.bouncerSceneContentViewModel.actionButton)
assertWithMessage("Bouncer action button not visible")
.that(bouncerActionButton)
.isNotNull()
@@ -430,54 +353,55 @@
@Test
fun bouncerActionButtonClick_duringCall_returnsToCall() =
testScope.runTest {
- setAuthMethod(AuthenticationMethodModel.Password)
- startPhoneCall()
- val actions by collectLastValue(lockscreenSceneActionsViewModel.actions)
+ kosmos.setAuthMethod(AuthenticationMethodModel.Password)
+ kosmos.startPhoneCall()
+ val actions by collectLastValue(kosmos.lockscreenUserActionsViewModel.actions)
val upDestinationSceneKey =
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
- emulateUserDrivenTransition(to = upDestinationSceneKey)
+ kosmos.emulateUserDrivenTransition(to = upDestinationSceneKey)
- val bouncerActionButton by collectLastValue(bouncerSceneContentViewModel.actionButton)
+ val bouncerActionButton by
+ collectLastValue(kosmos.bouncerSceneContentViewModel.actionButton)
assertWithMessage("Bouncer action button not visible during call")
.that(bouncerActionButton)
.isNotNull()
bouncerActionButton?.onClick?.invoke()
runCurrent()
- verify(telecomManager).showInCallScreen(any())
+ verify(kosmos.mockTelecomManager).showInCallScreen(any())
}
@Test
fun showBouncer_whenLockedSimIntroduced() =
testScope.runTest {
- setAuthMethod(AuthenticationMethodModel.None)
- introduceLockedSim()
- assertCurrentScene(Scenes.Bouncer)
+ kosmos.setAuthMethod(AuthenticationMethodModel.None)
+ kosmos.introduceLockedSim()
+ kosmos.assertCurrentScene(Scenes.Bouncer)
}
@Test
fun goesToGone_whenSimUnlocked_whileDeviceUnlocked() =
testScope.runTest {
- fakeSceneDataSource.pause()
- introduceLockedSim()
- emulatePendingTransitionProgress(expectedVisible = true)
- enterSimPin(
+ kosmos.fakeSceneDataSource.pause()
+ kosmos.introduceLockedSim()
+ kosmos.emulatePendingTransitionProgress(expectedVisible = true)
+ kosmos.enterSimPin(
authMethodAfterSimUnlock = AuthenticationMethodModel.None,
enableLockscreen = false
)
- assertCurrentScene(Scenes.Gone)
+ kosmos.assertCurrentScene(Scenes.Gone)
}
@Test
fun showLockscreen_whenSimUnlocked_whileDeviceLocked() =
testScope.runTest {
- fakeSceneDataSource.pause()
- introduceLockedSim()
- emulatePendingTransitionProgress(expectedVisible = true)
- enterSimPin(authMethodAfterSimUnlock = AuthenticationMethodModel.Pin)
- assertCurrentScene(Scenes.Lockscreen)
+ kosmos.fakeSceneDataSource.pause()
+ kosmos.introduceLockedSim()
+ kosmos.emulatePendingTransitionProgress(expectedVisible = true)
+ kosmos.enterSimPin(authMethodAfterSimUnlock = AuthenticationMethodModel.Pin)
+ kosmos.assertCurrentScene(Scenes.Lockscreen)
}
/**
@@ -485,8 +409,8 @@
*
* Note that this doesn't assert what the current scene is in the UI.
*/
- private fun TestScope.assertCurrentScene(expected: SceneKey) {
- runCurrent()
+ private fun Kosmos.assertCurrentScene(expected: SceneKey) {
+ testScope.runCurrent()
assertWithMessage("Current scene mismatch!")
.that(sceneContainerViewModel.currentScene.value)
.isEqualTo(expected)
@@ -498,7 +422,7 @@
* This can be different than the value in [SceneContainerViewModel.currentScene], by design, as
* the UI must gradually transition between scenes.
*/
- private fun getCurrentSceneInUi(): SceneKey {
+ private fun Kosmos.getCurrentSceneInUi(): SceneKey {
return when (val state = transitionState.value) {
is ObservableTransitionState.Idle -> state.currentScene
is ObservableTransitionState.Transition.ChangeScene -> state.fromScene
@@ -508,7 +432,7 @@
}
/** Updates the current authentication method and related states in the data layer. */
- private fun TestScope.setAuthMethod(
+ private fun Kosmos.setAuthMethod(
authMethod: AuthenticationMethodModel,
enableLockscreen: Boolean = true
) {
@@ -520,20 +444,20 @@
// Set the lockscreen enabled bit _before_ set the auth method as the code picks up on the
// lockscreen enabled bit _after_ the auth method is changed and the lockscreen enabled bit
// is not an observable that can trigger a new evaluation.
- kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(enableLockscreen)
- kosmos.fakeAuthenticationRepository.setAuthenticationMethod(authMethod)
- runCurrent()
+ fakeDeviceEntryRepository.setLockscreenEnabled(enableLockscreen)
+ fakeAuthenticationRepository.setAuthenticationMethod(authMethod)
+ testScope.runCurrent()
}
/** Emulates a phone call in progress. */
- private fun TestScope.startPhoneCall() {
- whenever(telecomManager.isInCall).thenReturn(true)
- kosmos.fakeTelephonyRepository.apply {
+ private fun Kosmos.startPhoneCall() {
+ whenever(mockTelecomManager.isInCall).thenReturn(true)
+ fakeTelephonyRepository.apply {
setHasTelephonyRadio(true)
setIsInCall(true)
setCallState(TelephonyManager.CALL_STATE_OFFHOOK)
}
- runCurrent()
+ testScope.runCurrent()
}
/**
@@ -543,14 +467,12 @@
*
* In order to use this, the [fakeSceneDataSource] must be paused before this method is called.
*/
- private fun TestScope.emulatePendingTransitionProgress(
- expectedVisible: Boolean = true,
- ) {
+ private fun Kosmos.emulatePendingTransitionProgress(expectedVisible: Boolean = true) {
assertWithMessage("The FakeSceneDataSource has to be paused for this to do anything.")
- .that(fakeSceneDataSource.isPaused)
+ .that(kosmos.fakeSceneDataSource.isPaused)
.isTrue()
- val to = fakeSceneDataSource.pendingScene ?: return
+ val to = kosmos.fakeSceneDataSource.pendingScene ?: return
val from = getCurrentSceneInUi()
if (to == from) {
@@ -568,19 +490,19 @@
isInitiatedByUserInput = false,
isUserInputOngoing = flowOf(false),
)
- runCurrent()
+ testScope.runCurrent()
// Report progress of transition.
while (progressFlow.value < 1f) {
progressFlow.value += 0.2f
- runCurrent()
+ testScope.runCurrent()
}
// End the transition and report the change.
transitionState.value = ObservableTransitionState.Idle(to)
- fakeSceneDataSource.unpause(force = true)
- runCurrent()
+ kosmos.fakeSceneDataSource.unpause(force = true)
+ testScope.runCurrent()
assertWithMessage("Visibility mismatch after scene transition from $from to $to!")
.that(sceneContainerViewModel.isVisible)
@@ -598,7 +520,7 @@
bouncerSceneJob?.cancel()
null
}
- runCurrent()
+ testScope.runCurrent()
}
/**
@@ -610,12 +532,10 @@
*
* @param to The scene to transition to.
*/
- private fun TestScope.emulateUserDrivenTransition(
- to: SceneKey?,
- ) {
+ private fun Kosmos.emulateUserDrivenTransition(to: SceneKey?) {
checkNotNull(to)
- fakeSceneDataSource.pause()
+ kosmos.fakeSceneDataSource.pause()
sceneInteractor.changeScene(to, "reason")
emulatePendingTransitionProgress(
@@ -630,17 +550,17 @@
*
* Not to be confused with [putDeviceToSleep], which may also instantly lock the device.
*/
- private suspend fun TestScope.lockDevice() {
+ private suspend fun Kosmos.lockDevice() {
val authMethod = authenticationInteractor.getAuthenticationMethod()
assertWithMessage("The authentication method of $authMethod is not secure, cannot lock!")
.that(authMethod.isSecure)
.isTrue()
- kosmos.sceneInteractor.changeScene(Scenes.Lockscreen, "")
- runCurrent()
+ sceneInteractor.changeScene(Scenes.Lockscreen, "")
+ testScope.runCurrent()
}
/** Unlocks the device by entering the correct PIN. Ends up in the Gone scene. */
- private fun TestScope.unlockDevice() {
+ private fun Kosmos.unlockDevice() {
assertWithMessage("Cannot unlock a device that's already unlocked!")
.that(deviceEntryInteractor.isUnlocked.value)
.isFalse()
@@ -662,12 +582,12 @@
*
* Does not assert that the device is locked or unlocked.
*/
- private fun TestScope.enterPin() {
+ private fun Kosmos.enterPin() {
assertWithMessage("Cannot enter PIN when not on the Bouncer scene!")
.that(getCurrentSceneInUi())
.isEqualTo(Scenes.Bouncer)
val authMethodViewModel by
- collectLastValue(bouncerSceneContentViewModel.authMethodViewModel)
+ testScope.collectLastValue(bouncerSceneContentViewModel.authMethodViewModel)
assertWithMessage("Cannot enter PIN when not using a PIN authentication method!")
.that(authMethodViewModel)
.isInstanceOf(PinBouncerViewModel::class.java)
@@ -677,7 +597,7 @@
pinBouncerViewModel.onPinButtonClicked(digit)
}
pinBouncerViewModel.onAuthenticateButtonClicked()
- runCurrent()
+ testScope.runCurrent()
}
/**
@@ -688,7 +608,7 @@
*
* Does not assert that the device is locked or unlocked.
*/
- private fun TestScope.enterSimPin(
+ private fun Kosmos.enterSimPin(
authMethodAfterSimUnlock: AuthenticationMethodModel = AuthenticationMethodModel.None,
enableLockscreen: Boolean = true,
) {
@@ -696,7 +616,7 @@
.that(getCurrentSceneInUi())
.isEqualTo(Scenes.Bouncer)
val authMethodViewModel by
- collectLastValue(bouncerSceneContentViewModel.authMethodViewModel)
+ testScope.collectLastValue(bouncerSceneContentViewModel.authMethodViewModel)
assertWithMessage("Cannot enter PIN when not using a PIN authentication method!")
.that(authMethodViewModel)
.isInstanceOf(PinBouncerViewModel::class.java)
@@ -706,26 +626,26 @@
pinBouncerViewModel.onPinButtonClicked(digit)
}
pinBouncerViewModel.onAuthenticateButtonClicked()
- kosmos.fakeMobileConnectionsRepository.isAnySimSecure.value = false
- runCurrent()
+ fakeMobileConnectionsRepository.isAnySimSecure.value = false
+ testScope.runCurrent()
setAuthMethod(authMethodAfterSimUnlock, enableLockscreen)
- runCurrent()
+ testScope.runCurrent()
}
/** Changes device wakefulness state from asleep to awake, going through intermediary states. */
- private fun TestScope.wakeUpDevice() {
+ private fun Kosmos.wakeUpDevice() {
val wakefulnessModel = powerInteractor.detailedWakefulness.value
assertWithMessage("Cannot wake up device as it's already awake!")
.that(wakefulnessModel.isAwake())
.isFalse()
powerInteractor.setAwakeForTest()
- runCurrent()
+ testScope.runCurrent()
}
/** Changes device wakefulness state from awake to asleep, going through intermediary states. */
- private suspend fun TestScope.putDeviceToSleep(
+ private suspend fun Kosmos.putDeviceToSleep(
instantlyLockDevice: Boolean = true,
) {
val wakefulnessModel = powerInteractor.detailedWakefulness.value
@@ -734,7 +654,7 @@
.isTrue()
powerInteractor.setAsleepForTest()
- runCurrent()
+ testScope.runCurrent()
if (instantlyLockDevice) {
lockDevice()
@@ -742,16 +662,16 @@
}
/** Emulates the dismissal of the IME (soft keyboard). */
- private fun TestScope.dismissIme() {
+ private fun Kosmos.dismissIme() {
(bouncerSceneContentViewModel.authMethodViewModel.value as? PasswordBouncerViewModel)?.let {
it.onImeDismissed()
- runCurrent()
+ testScope.runCurrent()
}
}
- private fun TestScope.introduceLockedSim() {
+ private fun Kosmos.introduceLockedSim() {
setAuthMethod(AuthenticationMethodModel.Sim)
- kosmos.fakeMobileConnectionsRepository.isAnySimSecure.value = true
- runCurrent()
+ fakeMobileConnectionsRepository.isAnySimSecure.value = true
+ testScope.runCurrent()
}
}
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 d3b51d1..d180460 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
@@ -19,7 +19,10 @@
package com.android.systemui.scene.domain.startable
import android.app.StatusBarManager
+import android.hardware.face.FaceManager
import android.os.PowerManager
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import android.view.Display
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -27,9 +30,14 @@
import com.android.compose.animation.scene.SceneKey
import com.android.internal.logging.uiEventLoggerFake
import com.android.internal.policy.IKeyguardDismissCallback
+import com.android.keyguard.AuthInteractionProperties
+import com.android.systemui.Flags
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.biometrics.data.repository.fingerprintPropertyRepository
+import com.android.systemui.biometrics.shared.model.FingerprintSensorType
+import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
import com.android.systemui.bouncer.domain.interactor.bouncerInteractor
import com.android.systemui.bouncer.shared.logging.BouncerUiEvent
@@ -39,8 +47,15 @@
import com.android.systemui.concurrency.fakeExecutor
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryHapticsInteractor
import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
+import com.android.systemui.deviceentry.shared.model.FailedFaceAuthenticationStatus
+import com.android.systemui.deviceentry.shared.model.SuccessFaceAuthenticationStatus
import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.haptics.msdl.fakeMSDLPlayer
+import com.android.systemui.haptics.vibratorHelper
+import com.android.systemui.keyevent.data.repository.fakeKeyEventRepository
+import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
import com.android.systemui.keyguard.data.repository.deviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.fakeBiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository
@@ -53,11 +68,15 @@
import com.android.systemui.keyguard.domain.interactor.keyguardEnabledInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.domain.interactor.scenetransition.lockscreenSceneTransitionInteractor
+import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
+import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
+import com.android.systemui.keyguard.shared.model.FailFingerprintAuthenticationStatus
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
import com.android.systemui.model.sysUiState
import com.android.systemui.power.data.repository.fakePowerRepository
+import com.android.systemui.power.data.repository.powerRepository
import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
import com.android.systemui.power.domain.interactor.powerInteractor
@@ -69,6 +88,7 @@
import com.android.systemui.scene.shared.model.fakeSceneDataSource
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.shared.system.QuickStepContract
+import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor
import com.android.systemui.statusbar.notification.data.repository.FakeHeadsUpRowRepository
import com.android.systemui.statusbar.notification.data.repository.HeadsUpRowRepository
@@ -80,11 +100,13 @@
import com.android.systemui.statusbar.sysuiStatusBarStateController
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.mock
+import com.google.android.msdl.data.model.MSDLToken
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -92,6 +114,8 @@
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.Mockito
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.never
import org.mockito.Mockito.times
@@ -105,18 +129,22 @@
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
+ private val deviceEntryHapticsInteractor by lazy { kosmos.deviceEntryHapticsInteractor }
private val sceneInteractor by lazy { kosmos.sceneInteractor }
private val bouncerInteractor by lazy { kosmos.bouncerInteractor }
private val faceAuthRepository by lazy { kosmos.fakeDeviceEntryFaceAuthRepository }
private val bouncerRepository by lazy { kosmos.fakeKeyguardBouncerRepository }
private val sysUiState = kosmos.sysUiState
private val falsingCollector = mock<FalsingCollector>().also { kosmos.falsingCollector = it }
+ private val vibratorHelper = mock<VibratorHelper>().also { kosmos.vibratorHelper = it }
private val fakeSceneDataSource = kosmos.fakeSceneDataSource
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 val msdlPlayer = kosmos.fakeMSDLPlayer
+ private val authInteractionProperties = AuthInteractionProperties()
private lateinit var underTest: SceneContainerStartable
@@ -634,6 +662,382 @@
}
@Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playSuccessHaptics_onSuccessfulLockscreenAuth_udfps() =
+ testScope.runTest {
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ val playSuccessHaptic by
+ collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+
+ setupBiometricAuth(hasUdfps = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+ underTest.start()
+ unlockWithFingerprintAuth()
+
+ assertThat(playSuccessHaptic).isNotNull()
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ verify(vibratorHelper)
+ .vibrateAuthSuccess(
+ "SceneContainerStartable, $currentSceneKey device-entry::success"
+ )
+ verify(vibratorHelper, never()).vibrateAuthError(anyString())
+
+ updateFingerprintAuthStatus(isSuccess = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playSuccessMSDLHaptics_onSuccessfulLockscreenAuth_udfps() =
+ testScope.runTest {
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ val playSuccessHaptic by
+ collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+
+ setupBiometricAuth(hasUdfps = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+ underTest.start()
+ unlockWithFingerprintAuth()
+
+ assertThat(playSuccessHaptic).isNotNull()
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.UNLOCK)
+ assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(authInteractionProperties)
+
+ updateFingerprintAuthStatus(isSuccess = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playSuccessHaptics_onSuccessfulLockscreenAuth_sfps() =
+ testScope.runTest {
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ val playSuccessHaptic by
+ collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+
+ setupBiometricAuth(hasSfps = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+ underTest.start()
+ allowHapticsOnSfps()
+ unlockWithFingerprintAuth()
+
+ assertThat(playSuccessHaptic).isNotNull()
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ verify(vibratorHelper)
+ .vibrateAuthSuccess(
+ "SceneContainerStartable, $currentSceneKey device-entry::success"
+ )
+ verify(vibratorHelper, never()).vibrateAuthError(anyString())
+
+ updateFingerprintAuthStatus(isSuccess = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playSuccessMSDLHaptics_onSuccessfulLockscreenAuth_sfps() =
+ testScope.runTest {
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ val playSuccessHaptic by
+ collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+
+ setupBiometricAuth(hasSfps = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+ underTest.start()
+ allowHapticsOnSfps()
+ unlockWithFingerprintAuth()
+
+ assertThat(playSuccessHaptic).isNotNull()
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.UNLOCK)
+ assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(authInteractionProperties)
+
+ updateFingerprintAuthStatus(isSuccess = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playErrorHaptics_onFailedLockscreenAuth_udfps() =
+ testScope.runTest {
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic)
+
+ setupBiometricAuth(hasUdfps = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+ underTest.start()
+ updateFingerprintAuthStatus(isSuccess = false)
+
+ assertThat(playErrorHaptic).isNotNull()
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ verify(vibratorHelper)
+ .vibrateAuthError("SceneContainerStartable, $currentSceneKey device-entry::error")
+ verify(vibratorHelper, never()).vibrateAuthSuccess(anyString())
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playMSDLErrorHaptics_onFailedLockscreenAuth_udfps() =
+ testScope.runTest {
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic)
+
+ setupBiometricAuth(hasUdfps = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+ underTest.start()
+ updateFingerprintAuthStatus(isSuccess = false)
+
+ assertThat(playErrorHaptic).isNotNull()
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.FAILURE)
+ assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(authInteractionProperties)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playErrorHaptics_onFailedLockscreenAuth_sfps() =
+ testScope.runTest {
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic)
+
+ setupBiometricAuth(hasSfps = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+ underTest.start()
+ updateFingerprintAuthStatus(isSuccess = false)
+
+ assertThat(playErrorHaptic).isNotNull()
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ verify(vibratorHelper)
+ .vibrateAuthError("SceneContainerStartable, $currentSceneKey device-entry::error")
+ verify(vibratorHelper, never()).vibrateAuthSuccess(anyString())
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playMSDLErrorHaptics_onFailedLockscreenAuth_sfps() =
+ testScope.runTest {
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic)
+
+ setupBiometricAuth(hasSfps = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+ underTest.start()
+ updateFingerprintAuthStatus(isSuccess = false)
+
+ assertThat(playErrorHaptic).isNotNull()
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.FAILURE)
+ assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(authInteractionProperties)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun skipsSuccessHaptics_whenPowerButtonDown_sfps() =
+ testScope.runTest {
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ val playSuccessHaptic by
+ collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+
+ setupBiometricAuth(hasSfps = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+ underTest.start()
+ allowHapticsOnSfps(isPowerButtonDown = true)
+ unlockWithFingerprintAuth()
+
+ assertThat(playSuccessHaptic).isNull()
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ verify(vibratorHelper, never())
+ .vibrateAuthSuccess(
+ "SceneContainerStartable, $currentSceneKey device-entry::success"
+ )
+ verify(vibratorHelper, never()).vibrateAuthError(anyString())
+
+ updateFingerprintAuthStatus(isSuccess = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun skipsMSDLSuccessHaptics_whenPowerButtonDown_sfps() =
+ testScope.runTest {
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ val playSuccessHaptic by
+ collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+
+ setupBiometricAuth(hasSfps = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+ underTest.start()
+ allowHapticsOnSfps(isPowerButtonDown = true)
+ unlockWithFingerprintAuth()
+
+ assertThat(playSuccessHaptic).isNull()
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(msdlPlayer.latestTokenPlayed).isNull()
+ assertThat(msdlPlayer.latestPropertiesPlayed).isNull()
+
+ updateFingerprintAuthStatus(isSuccess = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun skipsSuccessHaptics_whenPowerButtonRecentlyPressed_sfps() =
+ testScope.runTest {
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ val playSuccessHaptic by
+ collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+
+ setupBiometricAuth(hasSfps = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+ underTest.start()
+ allowHapticsOnSfps(lastPowerPress = 50)
+ unlockWithFingerprintAuth()
+
+ assertThat(playSuccessHaptic).isNull()
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ verify(vibratorHelper, never())
+ .vibrateAuthSuccess(
+ "SceneContainerStartable, $currentSceneKey device-entry::success"
+ )
+ verify(vibratorHelper, never()).vibrateAuthError(anyString())
+
+ updateFingerprintAuthStatus(isSuccess = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun skipsMSDLSuccessHaptics_whenPowerButtonRecentlyPressed_sfps() =
+ testScope.runTest {
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ val playSuccessHaptic by
+ collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic)
+
+ setupBiometricAuth(hasSfps = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+ underTest.start()
+ allowHapticsOnSfps(lastPowerPress = 50)
+ unlockWithFingerprintAuth()
+
+ assertThat(playSuccessHaptic).isNull()
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(msdlPlayer.latestTokenPlayed).isNull()
+ assertThat(msdlPlayer.latestPropertiesPlayed).isNull()
+
+ updateFingerprintAuthStatus(isSuccess = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun skipsErrorHaptics_whenPowerButtonDown_sfps() =
+ testScope.runTest {
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic)
+
+ setupBiometricAuth(hasSfps = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+ underTest.start()
+ kosmos.fakeKeyEventRepository.setPowerButtonDown(true)
+ updateFingerprintAuthStatus(isSuccess = false)
+
+ assertThat(playErrorHaptic).isNull()
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ verify(vibratorHelper, never())
+ .vibrateAuthError("SceneContainerStartable, $currentSceneKey device-entry::error")
+ verify(vibratorHelper, never()).vibrateAuthSuccess(anyString())
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun skipsMSDLErrorHaptics_whenPowerButtonDown_sfps() =
+ testScope.runTest {
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic)
+
+ setupBiometricAuth(hasSfps = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+ underTest.start()
+ kosmos.fakeKeyEventRepository.setPowerButtonDown(true)
+ updateFingerprintAuthStatus(isSuccess = false)
+
+ assertThat(playErrorHaptic).isNull()
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(msdlPlayer.latestTokenPlayed).isNull()
+ assertThat(msdlPlayer.latestPropertiesPlayed).isNull()
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun skipsFaceErrorHaptics_nonSfps_coEx() =
+ testScope.runTest {
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic)
+
+ setupBiometricAuth(hasUdfps = true, hasFace = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+ underTest.start()
+ updateFaceAuthStatus(isSuccess = false)
+
+ assertThat(playErrorHaptic).isNull()
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ verify(vibratorHelper, never())
+ .vibrateAuthError("SceneContainerStartable, $currentSceneKey device-entry::error")
+ verify(vibratorHelper, never()).vibrateAuthSuccess(anyString())
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun skipsMSDLFaceErrorHaptics_nonSfps_coEx() =
+ testScope.runTest {
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic)
+
+ setupBiometricAuth(hasUdfps = true, hasFace = true)
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isFalse()
+
+ underTest.start()
+ updateFaceAuthStatus(isSuccess = false)
+
+ assertThat(playErrorHaptic).isNull()
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ assertThat(msdlPlayer.latestTokenPlayed).isNull()
+ assertThat(msdlPlayer.latestPropertiesPlayed).isNull()
+ }
+
+ @Test
fun hydrateSystemUiState() =
testScope.runTest {
val transitionStateFlow = prepareState()
@@ -1192,41 +1596,6 @@
}
@Test
- fun hydrateWindowController_setBouncerShowing() =
- testScope.runTest {
- underTest.start()
- val notificationShadeWindowController = kosmos.notificationShadeWindowController
- val transitionStateFlow = prepareState(initialSceneKey = Scenes.Lockscreen)
- val currentScene by collectLastValue(sceneInteractor.currentScene)
- assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
- verify(notificationShadeWindowController, never()).setBouncerShowing(true)
- verify(notificationShadeWindowController, times(1)).setBouncerShowing(false)
-
- emulateSceneTransition(transitionStateFlow, Scenes.Bouncer)
- verify(notificationShadeWindowController, times(1)).setBouncerShowing(true)
- verify(notificationShadeWindowController, times(1)).setBouncerShowing(false)
-
- emulateSceneTransition(transitionStateFlow, Scenes.Lockscreen)
- verify(notificationShadeWindowController, times(1)).setBouncerShowing(true)
- verify(notificationShadeWindowController, times(2)).setBouncerShowing(false)
-
- kosmos.deviceEntryFingerprintAuthRepository.setAuthenticationStatus(
- SuccessFingerprintAuthenticationStatus(0, true)
- )
- assertThat(currentScene).isEqualTo(Scenes.Gone)
- verify(notificationShadeWindowController, times(1)).setBouncerShowing(true)
- verify(notificationShadeWindowController, times(2)).setBouncerShowing(false)
-
- emulateSceneTransition(transitionStateFlow, Scenes.Lockscreen)
- verify(notificationShadeWindowController, times(1)).setBouncerShowing(true)
- verify(notificationShadeWindowController, times(2)).setBouncerShowing(false)
-
- emulateSceneTransition(transitionStateFlow, Scenes.Bouncer)
- verify(notificationShadeWindowController, times(2)).setBouncerShowing(true)
- verify(notificationShadeWindowController, times(2)).setBouncerShowing(false)
- }
-
- @Test
fun hydrateWindowController_setKeyguardOccluded() =
testScope.runTest {
underTest.start()
@@ -1876,4 +2245,92 @@
FakeHeadsUpRowRepository(key = key, elementKey = Any()).apply {
this.isPinned.value = isPinned
}
+
+ private fun setFingerprintSensorType(fingerprintSensorType: FingerprintSensorType) {
+ kosmos.fingerprintPropertyRepository.setProperties(
+ sensorId = 0,
+ strength = SensorStrength.STRONG,
+ sensorType = fingerprintSensorType,
+ sensorLocations = mapOf(),
+ )
+ kosmos.biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
+ }
+
+ private fun setFaceEnrolled() {
+ kosmos.biometricSettingsRepository.setIsFaceAuthEnrolledAndEnabled(true)
+ }
+
+ private fun TestScope.allowHapticsOnSfps(
+ isPowerButtonDown: Boolean = false,
+ lastPowerPress: Long = 10000
+ ) {
+ kosmos.fakeKeyEventRepository.setPowerButtonDown(isPowerButtonDown)
+
+ kosmos.powerRepository.updateWakefulness(
+ WakefulnessState.AWAKE,
+ WakeSleepReason.POWER_BUTTON,
+ WakeSleepReason.POWER_BUTTON,
+ powerButtonLaunchGestureTriggered = false,
+ )
+
+ advanceTimeBy(lastPowerPress)
+ runCurrent()
+ }
+
+ private fun unlockWithFingerprintAuth() {
+ kosmos.fakeKeyguardRepository.setBiometricUnlockSource(
+ BiometricUnlockSource.FINGERPRINT_SENSOR
+ )
+ kosmos.fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockMode.UNLOCK_COLLAPSING)
+ }
+
+ private fun TestScope.setupBiometricAuth(
+ hasSfps: Boolean = false,
+ hasUdfps: Boolean = false,
+ hasFace: Boolean = false
+ ) {
+ if (hasSfps) {
+ setFingerprintSensorType(FingerprintSensorType.POWER_BUTTON)
+ }
+
+ if (hasUdfps) {
+ setFingerprintSensorType(FingerprintSensorType.UDFPS_ULTRASONIC)
+ }
+
+ if (hasFace) {
+ setFaceEnrolled()
+ }
+
+ prepareState(
+ authenticationMethod = AuthenticationMethodModel.Pin,
+ isDeviceUnlocked = false,
+ initialSceneKey = Scenes.Lockscreen,
+ )
+ }
+
+ private fun updateFingerprintAuthStatus(isSuccess: Boolean) {
+ if (isSuccess) {
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+ SuccessFingerprintAuthenticationStatus(0, true)
+ )
+ } else {
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+ FailFingerprintAuthenticationStatus
+ )
+ }
+ }
+
+ private fun updateFaceAuthStatus(isSuccess: Boolean) {
+ if (isSuccess) {
+ kosmos.fakeDeviceEntryFaceAuthRepository.setAuthenticationStatus(
+ SuccessFaceAuthenticationStatus(
+ successResult = Mockito.mock(FaceManager.AuthenticationResult::class.java)
+ )
+ )
+ } else {
+ kosmos.fakeDeviceEntryFaceAuthRepository.setAuthenticationStatus(
+ FailedFaceAuthenticationStatus()
+ )
+ }
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
similarity index 83%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneSceneActionsViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
index b526275..03106ec 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
@@ -43,17 +43,17 @@
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@EnableSceneContainer
-class GoneSceneActionsViewModelTest : SysuiTestCase() {
+class GoneUserActionsViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
private val shadeRepository by lazy { kosmos.shadeRepository }
- private lateinit var underTest: GoneSceneActionsViewModel
+ private lateinit var underTest: GoneUserActionsViewModel
@Before
fun setUp() {
underTest =
- GoneSceneActionsViewModel(
+ GoneUserActionsViewModel(
shadeInteractor = kosmos.shadeInteractor,
)
underTest.activateIn(testScope)
@@ -62,21 +62,21 @@
@Test
fun downTransitionKey_splitShadeEnabled_isGoneToSplitShade() =
testScope.runTest {
- val destinationScenes by collectLastValue(underTest.actions)
+ val userActions by collectLastValue(underTest.actions)
shadeRepository.setShadeLayoutWide(true)
runCurrent()
- assertThat(destinationScenes?.get(Swipe(SwipeDirection.Down))?.transitionKey)
+ assertThat(userActions?.get(Swipe(SwipeDirection.Down))?.transitionKey)
.isEqualTo(ToSplitShade)
}
@Test
fun downTransitionKey_splitShadeDisabled_isNull() =
testScope.runTest {
- val destinationScenes by collectLastValue(underTest.actions)
+ val userActions by collectLastValue(underTest.actions)
shadeRepository.setShadeLayoutWide(false)
runCurrent()
- assertThat(destinationScenes?.get(Swipe(SwipeDirection.Down))?.transitionKey).isNull()
+ assertThat(userActions?.get(Swipe(SwipeDirection.Down))?.transitionKey).isNull()
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
index 3558f17..a0bb017 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
@@ -18,9 +18,12 @@
package com.android.systemui.scene.ui.viewmodel
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import android.view.MotionEvent
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.DefaultEdgeDetector
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.domain.interactor.falsingInteractor
import com.android.systemui.classifier.fakeFalsingManager
@@ -31,10 +34,16 @@
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.fakeOverlaysByKeys
import com.android.systemui.scene.sceneContainerConfig
import com.android.systemui.scene.shared.logger.sceneLogger
+import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
+import com.android.systemui.shade.data.repository.fakeShadeRepository
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.shade.shared.flag.DualShade
+import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
@@ -58,6 +67,7 @@
private val testScope by lazy { kosmos.testScope }
private val sceneInteractor by lazy { kosmos.sceneInteractor }
private val fakeSceneDataSource by lazy { kosmos.fakeSceneDataSource }
+ private val fakeShadeRepository by lazy { kosmos.fakeShadeRepository }
private val sceneContainerConfig by lazy { kosmos.sceneContainerConfig }
private val falsingManager by lazy { kosmos.fakeFalsingManager }
@@ -73,6 +83,8 @@
sceneInteractor = sceneInteractor,
falsingInteractor = kosmos.falsingInteractor,
powerInteractor = kosmos.powerInteractor,
+ shadeInteractor = kosmos.shadeInteractor,
+ splitEdgeDetector = kosmos.splitEdgeDetector,
logger = kosmos.sceneLogger,
motionEventHandlerReceiver = { motionEventHandler ->
this@SceneContainerViewModelTest.motionEventHandler = motionEventHandler
@@ -243,4 +255,90 @@
assertThat(underTest.isVisible).isFalse()
}
+
+ @Test
+ fun getActionableContentKey_noOverlays_returnsCurrentScene() =
+ testScope.runTest {
+ val currentScene by collectLastValue(underTest.currentScene)
+ val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
+ assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+ assertThat(currentOverlays).isEmpty()
+
+ val actionableContentKey =
+ underTest.getActionableContentKey(
+ currentScene = checkNotNull(currentScene),
+ currentOverlays = checkNotNull(currentOverlays),
+ overlayByKey = kosmos.fakeOverlaysByKeys,
+ )
+
+ assertThat(actionableContentKey).isEqualTo(Scenes.Lockscreen)
+ }
+
+ @Test
+ fun getActionableContentKey_multipleOverlays_returnsTopOverlay() =
+ testScope.runTest {
+ val currentScene by collectLastValue(underTest.currentScene)
+ val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
+ fakeSceneDataSource.showOverlay(Overlays.QuickSettingsShade)
+ fakeSceneDataSource.showOverlay(Overlays.NotificationsShade)
+ assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+ assertThat(currentOverlays)
+ .containsExactly(
+ Overlays.QuickSettingsShade,
+ Overlays.NotificationsShade,
+ )
+
+ val actionableContentKey =
+ underTest.getActionableContentKey(
+ currentScene = checkNotNull(currentScene),
+ currentOverlays = checkNotNull(currentOverlays),
+ overlayByKey = kosmos.fakeOverlaysByKeys,
+ )
+
+ assertThat(actionableContentKey).isEqualTo(Overlays.QuickSettingsShade)
+ }
+
+ @Test
+ @DisableFlags(DualShade.FLAG_NAME)
+ fun edgeDetector_singleShade_usesDefaultEdgeDetector() =
+ testScope.runTest {
+ val shadeMode by collectLastValue(kosmos.shadeInteractor.shadeMode)
+ fakeShadeRepository.setShadeLayoutWide(false)
+ assertThat(shadeMode).isEqualTo(ShadeMode.Single)
+
+ assertThat(underTest.edgeDetector).isEqualTo(DefaultEdgeDetector)
+ }
+
+ @Test
+ @DisableFlags(DualShade.FLAG_NAME)
+ fun edgeDetector_splitShade_usesDefaultEdgeDetector() =
+ testScope.runTest {
+ val shadeMode by collectLastValue(kosmos.shadeInteractor.shadeMode)
+ fakeShadeRepository.setShadeLayoutWide(true)
+ assertThat(shadeMode).isEqualTo(ShadeMode.Split)
+
+ assertThat(underTest.edgeDetector).isEqualTo(DefaultEdgeDetector)
+ }
+
+ @Test
+ @EnableFlags(DualShade.FLAG_NAME)
+ fun edgeDetector_dualShade_narrowScreen_usesSplitEdgeDetector() =
+ testScope.runTest {
+ val shadeMode by collectLastValue(kosmos.shadeInteractor.shadeMode)
+ fakeShadeRepository.setShadeLayoutWide(false)
+
+ assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
+ assertThat(underTest.edgeDetector).isEqualTo(kosmos.splitEdgeDetector)
+ }
+
+ @Test
+ @EnableFlags(DualShade.FLAG_NAME)
+ fun edgeDetector_dualShade_wideScreen_usesSplitEdgeDetector() =
+ testScope.runTest {
+ val shadeMode by collectLastValue(kosmos.shadeInteractor.shadeMode)
+ fakeShadeRepository.setShadeLayoutWide(true)
+
+ assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
+ assertThat(underTest.edgeDetector).isEqualTo(kosmos.splitEdgeDetector)
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorTest.kt
new file mode 100644
index 0000000..3d76d28
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorTest.kt
@@ -0,0 +1,274 @@
+/*
+ * 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.scene.ui.viewmodel
+
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.End
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.Resolved.Bottom
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.Resolved.Left
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.Resolved.Right
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.Resolved.TopLeft
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.Resolved.TopRight
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.Start
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.TopEnd
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.TopStart
+import com.google.common.truth.Truth.assertThat
+import kotlin.test.assertFailsWith
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class SplitEdgeDetectorTest : SysuiTestCase() {
+
+ private val edgeSize = 40
+ private val screenWidth = 800
+ private val screenHeight = 600
+
+ private var edgeSplitFraction = 0.7f
+
+ private val underTest =
+ SplitEdgeDetector(
+ topEdgeSplitFraction = { edgeSplitFraction },
+ edgeSize = edgeSize.dp,
+ )
+
+ @Test
+ fun source_noEdge_detectsNothing() {
+ val detectedEdge =
+ swipeVerticallyFrom(
+ x = screenWidth / 2,
+ y = screenHeight / 2,
+ )
+ assertThat(detectedEdge).isNull()
+ }
+
+ @Test
+ fun source_swipeVerticallyOnTopLeft_detectsTopLeft() {
+ val detectedEdge =
+ swipeVerticallyFrom(
+ x = 1,
+ y = edgeSize - 1,
+ )
+ assertThat(detectedEdge).isEqualTo(TopLeft)
+ }
+
+ @Test
+ fun source_swipeHorizontallyOnTopLeft_detectsLeft() {
+ val detectedEdge =
+ swipeHorizontallyFrom(
+ x = 1,
+ y = edgeSize - 1,
+ )
+ assertThat(detectedEdge).isEqualTo(Left)
+ }
+
+ @Test
+ fun source_swipeVerticallyOnTopRight_detectsTopRight() {
+ val detectedEdge =
+ swipeVerticallyFrom(
+ x = screenWidth - 1,
+ y = edgeSize - 1,
+ )
+ assertThat(detectedEdge).isEqualTo(TopRight)
+ }
+
+ @Test
+ fun source_swipeHorizontallyOnTopRight_detectsRight() {
+ val detectedEdge =
+ swipeHorizontallyFrom(
+ x = screenWidth - 1,
+ y = edgeSize - 1,
+ )
+ assertThat(detectedEdge).isEqualTo(Right)
+ }
+
+ @Test
+ fun source_swipeVerticallyToLeftOfSplit_detectsTopLeft() {
+ val detectedEdge =
+ swipeVerticallyFrom(
+ x = (screenWidth * edgeSplitFraction).toInt() - 1,
+ y = edgeSize - 1,
+ )
+ assertThat(detectedEdge).isEqualTo(TopLeft)
+ }
+
+ @Test
+ fun source_swipeVerticallyToRightOfSplit_detectsTopRight() {
+ val detectedEdge =
+ swipeVerticallyFrom(
+ x = (screenWidth * edgeSplitFraction).toInt() + 1,
+ y = edgeSize - 1,
+ )
+ assertThat(detectedEdge).isEqualTo(TopRight)
+ }
+
+ @Test
+ fun source_edgeSplitFractionUpdatesDynamically() {
+ val middleX = (screenWidth * 0.5f).toInt()
+ val topY = 0
+
+ // Split closer to the right; middle of screen is considered "left".
+ edgeSplitFraction = 0.6f
+ assertThat(swipeVerticallyFrom(x = middleX, y = topY)).isEqualTo(TopLeft)
+
+ // Split closer to the left; middle of screen is considered "right".
+ edgeSplitFraction = 0.4f
+ assertThat(swipeVerticallyFrom(x = middleX, y = topY)).isEqualTo(TopRight)
+
+ // Illegal fraction.
+ edgeSplitFraction = 1.2f
+ assertFailsWith<IllegalArgumentException> { swipeVerticallyFrom(x = middleX, y = topY) }
+
+ // Illegal fraction.
+ edgeSplitFraction = -0.3f
+ assertFailsWith<IllegalArgumentException> { swipeVerticallyFrom(x = middleX, y = topY) }
+ }
+
+ @Test
+ fun source_swipeVerticallyOnBottom_detectsBottom() {
+ val detectedEdge =
+ swipeVerticallyFrom(
+ x = screenWidth / 3,
+ y = screenHeight - (edgeSize / 2),
+ )
+ assertThat(detectedEdge).isEqualTo(Bottom)
+ }
+
+ @Test
+ fun source_swipeHorizontallyOnBottom_detectsNothing() {
+ val detectedEdge =
+ swipeHorizontallyFrom(
+ x = screenWidth / 3,
+ y = screenHeight - (edgeSize - 1),
+ )
+ assertThat(detectedEdge).isNull()
+ }
+
+ @Test
+ fun source_swipeHorizontallyOnLeft_detectsLeft() {
+ val detectedEdge =
+ swipeHorizontallyFrom(
+ x = edgeSize - 1,
+ y = screenHeight / 2,
+ )
+ assertThat(detectedEdge).isEqualTo(Left)
+ }
+
+ @Test
+ fun source_swipeVerticallyOnLeft_detectsNothing() {
+ val detectedEdge =
+ swipeVerticallyFrom(
+ x = edgeSize - 1,
+ y = screenHeight / 2,
+ )
+ assertThat(detectedEdge).isNull()
+ }
+
+ @Test
+ fun source_swipeHorizontallyOnRight_detectsRight() {
+ val detectedEdge =
+ swipeHorizontallyFrom(
+ x = screenWidth - edgeSize + 1,
+ y = screenHeight / 2,
+ )
+ assertThat(detectedEdge).isEqualTo(Right)
+ }
+
+ @Test
+ fun source_swipeVerticallyOnRight_detectsNothing() {
+ val detectedEdge =
+ swipeVerticallyFrom(
+ x = screenWidth - edgeSize + 1,
+ y = screenHeight / 2,
+ )
+ assertThat(detectedEdge).isNull()
+ }
+
+ @Test
+ fun resolve_startInLtr_resolvesLeft() {
+ val resolvedEdge = Start.resolve(LayoutDirection.Ltr)
+ assertThat(resolvedEdge).isEqualTo(Left)
+ }
+
+ @Test
+ fun resolve_startInRtl_resolvesRight() {
+ val resolvedEdge = Start.resolve(LayoutDirection.Rtl)
+ assertThat(resolvedEdge).isEqualTo(Right)
+ }
+
+ @Test
+ fun resolve_endInLtr_resolvesRight() {
+ val resolvedEdge = End.resolve(LayoutDirection.Ltr)
+ assertThat(resolvedEdge).isEqualTo(Right)
+ }
+
+ @Test
+ fun resolve_endInRtl_resolvesLeft() {
+ val resolvedEdge = End.resolve(LayoutDirection.Rtl)
+ assertThat(resolvedEdge).isEqualTo(Left)
+ }
+
+ @Test
+ fun resolve_topStartInLtr_resolvesTopLeft() {
+ val resolvedEdge = TopStart.resolve(LayoutDirection.Ltr)
+ assertThat(resolvedEdge).isEqualTo(TopLeft)
+ }
+
+ @Test
+ fun resolve_topStartInRtl_resolvesTopRight() {
+ val resolvedEdge = TopStart.resolve(LayoutDirection.Rtl)
+ assertThat(resolvedEdge).isEqualTo(TopRight)
+ }
+
+ @Test
+ fun resolve_topEndInLtr_resolvesTopRight() {
+ val resolvedEdge = TopEnd.resolve(LayoutDirection.Ltr)
+ assertThat(resolvedEdge).isEqualTo(TopRight)
+ }
+
+ @Test
+ fun resolve_topEndInRtl_resolvesTopLeft() {
+ val resolvedEdge = TopEnd.resolve(LayoutDirection.Rtl)
+ assertThat(resolvedEdge).isEqualTo(TopLeft)
+ }
+
+ private fun swipeVerticallyFrom(x: Int, y: Int): SceneContainerEdge.Resolved? {
+ return swipeFrom(x, y, Orientation.Vertical)
+ }
+
+ private fun swipeHorizontallyFrom(x: Int, y: Int): SceneContainerEdge.Resolved? {
+ return swipeFrom(x, y, Orientation.Horizontal)
+ }
+
+ private fun swipeFrom(x: Int, y: Int, orientation: Orientation): SceneContainerEdge.Resolved? {
+ return underTest.source(
+ layoutSize = IntSize(width = screenWidth, height = screenHeight),
+ position = IntOffset(x, y),
+ density = Density(1f),
+ orientation = orientation,
+ )
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/UserActionsViewModelTest.kt
similarity index 95%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/UserActionsViewModelTest.kt
index 900f2a4..972afb5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/UserActionsViewModelTest.kt
@@ -42,12 +42,12 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
-class SceneActionsViewModelTest : SysuiTestCase() {
+class UserActionsViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
- private val underTest = FakeSceneActionsViewModel()
+ private val underTest = FakeUserActionsViewModel()
@Test
fun actions_emptyBeforeActivation() =
@@ -115,7 +115,7 @@
assertThat(actions).isEmpty()
}
- private class FakeSceneActionsViewModel : SceneActionsViewModel() {
+ private class FakeUserActionsViewModel : UserActionsViewModel() {
val upstream = MutableStateFlow<Map<UserAction, UserActionResult>>(emptyMap())
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 3283ea1..9464c75 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,6 @@
import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
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.parameterizeSceneContainerFlag
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
@@ -39,6 +38,7 @@
import com.android.systemui.power.data.repository.fakePowerRepository
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.power.shared.model.WakefulnessState
+import com.android.systemui.shade.data.repository.fakeShadeRepository
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.shade.shadeTestUtil
import com.android.systemui.shade.shared.flag.DualShade
@@ -66,18 +66,18 @@
@SmallTest
@RunWith(ParameterizedAndroidJunit4::class)
class ShadeInteractorImplTest(flags: FlagsParameterization) : SysuiTestCase() {
- val kosmos = testKosmos()
- val testScope = kosmos.testScope
- val configurationRepository by lazy { kosmos.fakeConfigurationRepository }
- val deviceProvisioningRepository by lazy { kosmos.fakeDeviceProvisioningRepository }
- val disableFlagsRepository by lazy { kosmos.fakeDisableFlagsRepository }
- val keyguardRepository by lazy { kosmos.fakeKeyguardRepository }
- val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository }
- val powerRepository by lazy { kosmos.fakePowerRepository }
- val shadeTestUtil by lazy { kosmos.shadeTestUtil }
- val userRepository by lazy { kosmos.fakeUserRepository }
- val userSetupRepository by lazy { kosmos.fakeUserSetupRepository }
- val dozeParameters by lazy { kosmos.dozeParameters }
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val deviceProvisioningRepository by lazy { kosmos.fakeDeviceProvisioningRepository }
+ private val disableFlagsRepository by lazy { kosmos.fakeDisableFlagsRepository }
+ private val keyguardRepository by lazy { kosmos.fakeKeyguardRepository }
+ private val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository }
+ private val powerRepository by lazy { kosmos.fakePowerRepository }
+ private val shadeRepository by lazy { kosmos.fakeShadeRepository }
+ private val shadeTestUtil by lazy { kosmos.shadeTestUtil }
+ private val userRepository by lazy { kosmos.fakeUserRepository }
+ private val userSetupRepository by lazy { kosmos.fakeUserSetupRepository }
+ private val dozeParameters by lazy { kosmos.dozeParameters }
lateinit var underTest: ShadeInteractorImpl
@@ -497,4 +497,24 @@
assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
}
+
+ @Test
+ fun getTopEdgeSplitFraction_narrowScreen_splitInHalf() =
+ testScope.runTest {
+ // Ensure isShadeLayoutWide is collected.
+ val isShadeLayoutWide by collectLastValue(underTest.isShadeLayoutWide)
+ shadeRepository.setShadeLayoutWide(false)
+
+ assertThat(underTest.getTopEdgeSplitFraction()).isEqualTo(0.5f)
+ }
+
+ @Test
+ fun getTopEdgeSplitFraction_wideScreen_leftSideLarger() =
+ testScope.runTest {
+ // Ensure isShadeLayoutWide is collected.
+ val isShadeLayoutWide by collectLastValue(underTest.isShadeLayoutWide)
+ shadeRepository.setShadeLayoutWide(true)
+
+ assertThat(underTest.getTopEdgeSplitFraction()).isGreaterThan(0.5f)
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModelTest.kt
index 8b97739..f5022b9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModelTest.kt
@@ -16,18 +16,28 @@
package com.android.systemui.shade.ui.viewmodel
+import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.ObservableTransitionState
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.coroutines.collectLastValue
+import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.testKosmos
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.Test
import org.junit.runner.RunWith
@@ -150,4 +160,90 @@
)
assertThat(isKeyguardOccluded).isTrue()
}
+
+ @Test
+ @EnableSceneContainer
+ fun withSceneContainer_bouncerShowing_providesTheCorrectState() =
+ testScope.runTest {
+ val bouncerShowing by collectLastValue(underTest.isBouncerShowing)
+
+ val transitionState =
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Idle(Scenes.Lockscreen)
+ )
+ kosmos.sceneInteractor.setTransitionState(transitionState)
+ runCurrent()
+ assertThat(bouncerShowing).isFalse()
+
+ transitionState.value = ObservableTransitionState.Idle(Scenes.Bouncer)
+ runCurrent()
+ assertThat(bouncerShowing).isTrue()
+ }
+
+ @Test
+ @EnableFlags(com.android.systemui.Flags.FLAG_COMPOSE_BOUNCER)
+ fun withComposeBouncer_bouncerShowing_providesTheCorrectState() =
+ testScope.runTest {
+ val bouncerShowing by collectLastValue(underTest.isBouncerShowing)
+
+ kosmos.fakeKeyguardBouncerRepository.setPrimaryShow(isShowing = false)
+ runCurrent()
+ assertThat(bouncerShowing).isFalse()
+
+ kosmos.fakeKeyguardBouncerRepository.setPrimaryShow(isShowing = true)
+ runCurrent()
+ assertThat(bouncerShowing).isTrue()
+ }
+
+ @Test
+ @EnableSceneContainer
+ fun withSceneContainer_doesBouncerRequireIme_providesTheCorrectState() =
+ testScope.runTest {
+ val bouncerRequiresIme by collectLastValue(underTest.doesBouncerRequireIme)
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+ AuthenticationMethodModel.Pin
+ )
+
+ val transitionState =
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Idle(Scenes.Bouncer)
+ )
+ kosmos.sceneInteractor.setTransitionState(transitionState)
+ runCurrent()
+ assertThat(bouncerRequiresIme).isFalse()
+
+ // go back to lockscreen
+ transitionState.value = ObservableTransitionState.Idle(Scenes.Lockscreen)
+ runCurrent()
+
+ // change auth method
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+ AuthenticationMethodModel.Password
+ )
+ // go back to bouncer
+ transitionState.value = ObservableTransitionState.Idle(Scenes.Bouncer)
+ runCurrent()
+ assertThat(bouncerRequiresIme).isTrue()
+ }
+
+ @Test
+ @EnableFlags(com.android.systemui.Flags.FLAG_COMPOSE_BOUNCER)
+ fun withComposeBouncer_doesBouncerRequireIme_providesTheCorrectState() =
+ testScope.runTest {
+ val bouncerRequiresIme by collectLastValue(underTest.doesBouncerRequireIme)
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+ AuthenticationMethodModel.Pin
+ )
+
+ kosmos.fakeKeyguardBouncerRepository.setPrimaryShow(isShowing = true)
+ runCurrent()
+ assertThat(bouncerRequiresIme).isFalse()
+
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+ AuthenticationMethodModel.Password
+ )
+ kosmos.fakeKeyguardBouncerRepository.setPrimaryShow(isShowing = true)
+ runCurrent()
+ assertThat(bouncerRequiresIme).isFalse()
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt
similarity index 98%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt
index a931e65..9f3e126e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt
@@ -64,7 +64,7 @@
@TestableLooper.RunWithLooper
@EnableSceneContainer
@DisableFlags(DualShade.FLAG_NAME)
-class ShadeSceneActionsViewModelTest : SysuiTestCase() {
+class ShadeUserActionsViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
@@ -72,7 +72,7 @@
private val shadeRepository by lazy { kosmos.shadeRepository }
private val qsSceneAdapter by lazy { kosmos.fakeQSSceneAdapter }
- private val underTest: ShadeSceneActionsViewModel by lazy { kosmos.shadeSceneActionsViewModel }
+ private val underTest: ShadeUserActionsViewModel by lazy { kosmos.shadeUserActionsViewModel }
@Before
fun setUp() {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
index 75ecb2c..beba162 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
@@ -133,7 +133,8 @@
mVisibilityLocationProvider,
mVisualStabilityProvider,
mWakefulnessLifecycle,
- mKosmos.getCommunalInteractor(),
+ mKosmos.getCommunalSceneInteractor(),
+ mKosmos.getShadeInteractor(),
mKosmos.getKeyguardTransitionInteractor(),
mLogger);
mCoordinator.attach(mNotifPipeline);
@@ -561,11 +562,12 @@
@Test
public void testCommunalShowingWillNotSuppressReordering() {
- // GIVEN panel is expanded and communal is showing
+ // GIVEN panel is expanded, communal is showing, and QS is collapsed
setPulsing(false);
setFullyDozed(false);
setSleepy(false);
setPanelExpanded(true);
+ setQsExpanded(false);
setCommunalShowing(true);
// Reordering should be allowed
@@ -573,6 +575,20 @@
}
@Test
+ public void testQsExpandedOverCommunalWillSuppressReordering() {
+ // GIVEN panel is expanded and communal is showing, but QS is expanded
+ setPulsing(false);
+ setFullyDozed(false);
+ setSleepy(false);
+ setPanelExpanded(true);
+ setQsExpanded(true);
+ setCommunalShowing(true);
+
+ // Reordering should not be allowed
+ assertFalse(mNotifStabilityManager.isEntryReorderingAllowed(mEntry));
+ }
+
+ @Test
public void testQueryingEntryReorderingButNotReportingReorderSuppressedDoesNotInvalidate() {
// GIVEN visual stability is being maintained b/c panel is expanded
setPulsing(false);
@@ -631,7 +647,12 @@
new ObservableTransitionState.Idle(
isShowing ? CommunalScenes.Communal : CommunalScenes.Blank)
);
- mKosmos.getCommunalRepository().setTransitionState(showingFlow);
+ mKosmos.getCommunalSceneInteractor().setTransitionState(showingFlow);
+ mTestScope.getTestScheduler().runCurrent();
+ }
+
+ private void setQsExpanded(boolean isExpanded) {
+ mKosmos.getShadeRepository().setQsExpansion(isExpanded ? 1.0f : 0.0f);
mTestScope.getTestScheduler().runCurrent();
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt
index 840aa92..26e1a4d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt
@@ -26,6 +26,7 @@
import com.android.settingslib.notification.data.repository.updateNotificationPolicy
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.flags.Flags
import com.android.systemui.flags.andSceneContainer
@@ -36,6 +37,7 @@
import com.android.systemui.power.data.repository.fakePowerRepository
import com.android.systemui.power.shared.model.WakefulnessState
import com.android.systemui.res.R
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.shade.shadeTestUtil
import com.android.systemui.statusbar.data.repository.fakeRemoteInputRepository
import com.android.systemui.statusbar.notification.data.repository.FakeHeadsUpRowRepository
@@ -51,6 +53,7 @@
import com.android.systemui.util.ui.value
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -153,7 +156,7 @@
fun shouldShowEmptyShadeView_trueWhenNoNotifs() =
testScope.runTest {
val shouldShowEmptyShadeView by collectLastValue(underTest.shouldShowEmptyShadeView)
- val shouldIncludeFooterView by collectLastValue(underTest.shouldIncludeFooterView)
+ val shouldIncludeFooterView by collectFooterViewVisibility()
// WHEN has no notifs
activeNotificationListRepository.setActiveNotifs(count = 0)
@@ -196,7 +199,7 @@
fun shouldShowEmptyShadeView_trueWhenQsExpandedInSplitShade() =
testScope.runTest {
val shouldShowEmptyShadeView by collectLastValue(underTest.shouldShowEmptyShadeView)
- val shouldIncludeFooterView by collectLastValue(underTest.shouldIncludeFooterView)
+ val shouldIncludeFooterView by collectFooterViewVisibility()
// WHEN has no notifs
activeNotificationListRepository.setActiveNotifs(count = 0)
@@ -217,7 +220,7 @@
fun shouldShowEmptyShadeView_trueWhenLockedShade() =
testScope.runTest {
val shouldShowEmptyShadeView by collectLastValue(underTest.shouldShowEmptyShadeView)
- val shouldIncludeFooterView by collectLastValue(underTest.shouldIncludeFooterView)
+ val shouldIncludeFooterView by collectFooterViewVisibility()
// WHEN has no notifs
activeNotificationListRepository.setActiveNotifs(count = 0)
@@ -315,7 +318,7 @@
@Test
fun shouldIncludeFooterView_trueWhenShade() =
testScope.runTest {
- val shouldIncludeFooterView by collectLastValue(underTest.shouldIncludeFooterView)
+ val shouldIncludeFooterView by collectFooterViewVisibility()
val shouldShowEmptyShadeView by collectLastValue(underTest.shouldShowEmptyShadeView)
// WHEN has notifs
@@ -333,7 +336,7 @@
@Test
fun shouldIncludeFooterView_trueWhenLockedShade() =
testScope.runTest {
- val shouldIncludeFooterView by collectLastValue(underTest.shouldIncludeFooterView)
+ val shouldIncludeFooterView by collectFooterViewVisibility()
val shouldShowEmptyShadeView by collectLastValue(underTest.shouldShowEmptyShadeView)
// WHEN has notifs
@@ -351,7 +354,7 @@
@Test
fun shouldIncludeFooterView_falseWhenKeyguard() =
testScope.runTest {
- val shouldInclude by collectLastValue(underTest.shouldIncludeFooterView)
+ val shouldInclude by collectFooterViewVisibility()
// WHEN has notifs
activeNotificationListRepository.setActiveNotifs(count = 2)
@@ -366,7 +369,7 @@
@Test
fun shouldIncludeFooterView_falseWhenUserNotSetUp() =
testScope.runTest {
- val shouldInclude by collectLastValue(underTest.shouldIncludeFooterView)
+ val shouldInclude by collectFooterViewVisibility()
// WHEN has notifs
activeNotificationListRepository.setActiveNotifs(count = 2)
@@ -384,7 +387,7 @@
@Test
fun shouldIncludeFooterView_falseWhenStartingToSleep() =
testScope.runTest {
- val shouldInclude by collectLastValue(underTest.shouldIncludeFooterView)
+ val shouldInclude by collectFooterViewVisibility()
// WHEN has notifs
activeNotificationListRepository.setActiveNotifs(count = 2)
@@ -402,7 +405,7 @@
@Test
fun shouldIncludeFooterView_falseWhenQsExpandedDefault() =
testScope.runTest {
- val shouldInclude by collectLastValue(underTest.shouldIncludeFooterView)
+ val shouldInclude by collectFooterViewVisibility()
// WHEN has notifs
activeNotificationListRepository.setActiveNotifs(count = 2)
@@ -421,7 +424,7 @@
@Test
fun shouldIncludeFooterView_trueWhenQsExpandedSplitShade() =
testScope.runTest {
- val shouldIncludeFooterView by collectLastValue(underTest.shouldIncludeFooterView)
+ val shouldIncludeFooterView by collectFooterViewVisibility()
val shouldShowEmptyShadeView by collectLastValue(underTest.shouldShowEmptyShadeView)
// WHEN has notifs
@@ -444,7 +447,7 @@
@Test
fun shouldIncludeFooterView_falseWhenRemoteInputActive() =
testScope.runTest {
- val shouldInclude by collectLastValue(underTest.shouldIncludeFooterView)
+ val shouldInclude by collectFooterViewVisibility()
// WHEN has notifs
activeNotificationListRepository.setActiveNotifs(count = 2)
@@ -462,7 +465,7 @@
@Test
fun shouldIncludeFooterView_animatesWhenShade() =
testScope.runTest {
- val shouldInclude by collectLastValue(underTest.shouldIncludeFooterView)
+ val shouldInclude by collectFooterViewVisibility()
// WHEN has notifs
activeNotificationListRepository.setActiveNotifs(count = 2)
@@ -478,7 +481,7 @@
@Test
fun shouldIncludeFooterView_notAnimatingOnKeyguard() =
testScope.runTest {
- val shouldInclude by collectLastValue(underTest.shouldIncludeFooterView)
+ val shouldInclude by collectFooterViewVisibility()
// WHEN has notifs
activeNotificationListRepository.setActiveNotifs(count = 2)
@@ -492,6 +495,22 @@
}
@Test
+ @EnableSceneContainer
+ fun shouldShowFooterView_falseWhenShadeIsClosed() =
+ testScope.runTest {
+ val shouldShow by collectLastValue(underTest.shouldShowFooterView)
+
+ // WHEN shade is closed
+ fakeKeyguardRepository.setStatusBarState(StatusBarState.SHADE)
+ shadeTestUtil.setShadeExpansion(0f)
+ runCurrent()
+
+ // THEN footer is hidden
+ assertThat(shouldShow?.value).isFalse()
+ }
+
+ @Test
+ @DisableSceneContainer
fun shouldHideFooterView_trueWhenShadeIsClosed() =
testScope.runTest {
val shouldHide by collectLastValue(underTest.shouldHideFooterView)
@@ -506,6 +525,7 @@
}
@Test
+ @DisableSceneContainer
fun shouldHideFooterView_falseWhenShadeIsOpen() =
testScope.runTest {
val shouldHide by collectLastValue(underTest.shouldHideFooterView)
@@ -520,6 +540,7 @@
}
@Test
+ @DisableSceneContainer
fun shouldHideFooterView_falseWhenQSPartiallyOpen() =
testScope.runTest {
val shouldHide by collectLastValue(underTest.shouldHideFooterView)
@@ -642,4 +663,10 @@
assertThat(animationsEnabled).isTrue()
}
+
+ private fun TestScope.collectFooterViewVisibility() =
+ collectLastValue(
+ if (SceneContainerFlag.isEnabled) underTest.shouldShowFooterView
+ else underTest.shouldIncludeFooterView
+ )
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
index a6fdd03..b5dbc3f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
@@ -22,8 +22,6 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.demomode.DemoMode
import com.android.systemui.demomode.DemoModeController
-import com.android.systemui.flags.FakeFeatureFlagsClassic
-import com.android.systemui.flags.Flags
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.connectivity.WifiPickerTrackerFactory
@@ -73,11 +71,6 @@
private val demoModelFlow = MutableStateFlow<FakeWifiEventModel?>(null)
private val mainExecutor = FakeExecutor(FakeSystemClock())
- private val featureFlags =
- FakeFeatureFlagsClassic().also {
- it.set(Flags.INSTANT_TETHER, true)
- it.set(Flags.WIFI_SECONDARY_NETWORKS, true)
- }
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
@@ -93,7 +86,6 @@
realImpl =
WifiRepositoryImpl(
- featureFlags,
testScope.backgroundScope,
mainExecutor,
testDispatcher,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt
index 84c728c..b9ca8fc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt
@@ -93,7 +93,7 @@
fun ssid_carrierMergedNetwork_outputsNull() =
testScope.runTest {
wifiRepository.setWifiNetwork(
- WifiNetworkModel.CarrierMerged(networkId = 1, subscriptionId = 2, level = 1)
+ WifiNetworkModel.CarrierMerged(subscriptionId = 2, level = 1)
)
var latest: String? = "default"
@@ -106,53 +106,10 @@
}
@Test
- fun ssid_isPasspointAccessPoint_outputsPasspointName() =
- testScope.runTest {
- wifiRepository.setWifiNetwork(
- WifiNetworkModel.Active(
- networkId = 1,
- level = 1,
- isPasspointAccessPoint = true,
- passpointProviderFriendlyName = "friendly",
- )
- )
-
- var latest: String? = null
- val job = underTest.ssid.onEach { latest = it }.launchIn(this)
- runCurrent()
-
- assertThat(latest).isEqualTo("friendly")
-
- job.cancel()
- }
-
- @Test
- fun ssid_isOnlineSignUpForPasspoint_outputsPasspointName() =
- testScope.runTest {
- wifiRepository.setWifiNetwork(
- WifiNetworkModel.Active(
- networkId = 1,
- level = 1,
- isOnlineSignUpForPasspointAccessPoint = true,
- passpointProviderFriendlyName = "friendly",
- )
- )
-
- var latest: String? = null
- val job = underTest.ssid.onEach { latest = it }.launchIn(this)
- runCurrent()
-
- assertThat(latest).isEqualTo("friendly")
-
- job.cancel()
- }
-
- @Test
fun ssid_unknownSsid_outputsNull() =
testScope.runTest {
wifiRepository.setWifiNetwork(
WifiNetworkModel.Active(
- networkId = 1,
level = 1,
ssid = WifiManager.UNKNOWN_SSID,
)
@@ -172,7 +129,6 @@
testScope.runTest {
wifiRepository.setWifiNetwork(
WifiNetworkModel.Active(
- networkId = 1,
level = 1,
ssid = "MyAwesomeWifiNetwork",
)
@@ -234,11 +190,9 @@
testScope.runTest {
val wifiNetwork =
WifiNetworkModel.Active(
- networkId = 45,
isValidated = true,
level = 3,
ssid = "AB",
- passpointProviderFriendlyName = "friendly"
)
wifiRepository.setWifiNetwork(wifiNetwork)
@@ -346,7 +300,6 @@
wifiRepository.setWifiNetwork(
WifiNetworkModel.Active(
ssid = "ssid 2",
- networkId = 1,
level = 2,
)
)
@@ -367,7 +320,6 @@
wifiRepository.setWifiNetwork(
WifiNetworkModel.Active(
ssid = "ssid 2",
- networkId = 1,
level = 2,
)
)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
index 1237347..72a45b9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
@@ -25,14 +25,14 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.ContentDescription.Companion.loadContentDescription
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
import com.android.systemui.statusbar.connectivity.WifiIcons
import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
@@ -44,6 +44,7 @@
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel.Companion.viewModelForLocation
+import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.TestScope
@@ -58,10 +59,11 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class WifiViewModelTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
private lateinit var underTest: WifiViewModel
- @Mock private lateinit var tableLogBuffer: TableLogBuffer
+ private val tableLogBuffer = logcatTableLogBuffer(kosmos, "WifiViewModelTest")
@Mock private lateinit var connectivityConstants: ConnectivityConstants
@Mock private lateinit var wifiConstants: WifiConstants
private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
@@ -86,7 +88,7 @@
AirplaneModeInteractor(
airplaneModeRepository,
connectivityRepository,
- FakeMobileConnectionsRepository(),
+ kosmos.fakeMobileConnectionsRepository,
),
tableLogBuffer,
testScope.backgroundScope,
@@ -113,9 +115,7 @@
val latestKeyguard by collectLastValue(keyguard.wifiIcon)
val latestQs by collectLastValue(qs.wifiIcon)
- wifiRepository.setWifiNetwork(
- WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 1)
- )
+ wifiRepository.setWifiNetwork(WifiNetworkModel.Active(isValidated = true, level = 1))
assertThat(latestHome).isInstanceOf(WifiIcon.Visible::class.java)
assertThat(latestHome).isEqualTo(latestKeyguard)
@@ -130,7 +130,6 @@
// Even WHEN the network has a valid hotspot type
wifiRepository.setWifiNetwork(
WifiNetworkModel.Active(
- NETWORK_ID,
isValidated = true,
level = 1,
hotspotDeviceType = WifiNetworkModel.HotspotDeviceType.LAPTOP,
@@ -192,9 +191,7 @@
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
createAndSetViewModel()
- wifiRepository.setWifiNetwork(
- WifiNetworkModel.Active(NETWORK_ID, ssid = null, level = 1)
- )
+ wifiRepository.setWifiNetwork(WifiNetworkModel.Active(ssid = null, level = 1))
val activityIn by collectLastValue(underTest.isActivityInViewVisible)
val activityOut by collectLastValue(underTest.isActivityOutViewVisible)
@@ -217,9 +214,7 @@
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
createAndSetViewModel()
- wifiRepository.setWifiNetwork(
- WifiNetworkModel.Active(NETWORK_ID, ssid = null, level = 1)
- )
+ wifiRepository.setWifiNetwork(WifiNetworkModel.Active(ssid = null, level = 1))
val activityIn by collectLastValue(underTest.isActivityInViewVisible)
val activityOut by collectLastValue(underTest.isActivityOutViewVisible)
@@ -468,8 +463,6 @@
}
companion object {
- private const val NETWORK_ID = 2
- private val ACTIVE_VALID_WIFI_NETWORK =
- WifiNetworkModel.Active(NETWORK_ID, ssid = "AB", level = 1)
+ private val ACTIVE_VALID_WIFI_NETWORK = WifiNetworkModel.Active(ssid = "AB", level = 1)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModelTest.kt
index 4cf924a..cb6dc19 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModelTest.kt
@@ -20,11 +20,12 @@
import androidx.test.filters.SmallTest
import com.android.internal.logging.uiEventLogger
import com.android.systemui.SysuiTestCase
+import com.android.systemui.accessibility.data.repository.captioningRepository
+import com.android.systemui.accessibility.domain.interactor.captioningInteractor
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
-import com.android.systemui.view.accessibility.data.repository.captioningInteractor
-import com.android.systemui.view.accessibility.data.repository.captioningRepository
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
@@ -49,7 +50,7 @@
CaptioningViewModel(
context,
captioningInteractor,
- testScope.backgroundScope,
+ applicationCoroutineScope,
uiEventLogger,
)
}
diff --git a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceConfigPlugin.kt b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceConfigPlugin.kt
index 509f022..84f39af 100644
--- a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceConfigPlugin.kt
+++ b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceConfigPlugin.kt
@@ -21,4 +21,6 @@
interface BcSmartspaceConfigPlugin {
/** Gets default date/weather disabled status. */
val isDefaultDateWeatherDisabled: Boolean
+ /** Gets if Smartspace should use ViewPager2 */
+ val isViewPager2Enabled: Boolean
}
diff --git a/packages/SystemUI/res/drawable/arrow_pointing_down.xml b/packages/SystemUI/res/drawable/arrow_pointing_down.xml
index be39683..ca573c7 100644
--- a/packages/SystemUI/res/drawable/arrow_pointing_down.xml
+++ b/packages/SystemUI/res/drawable/arrow_pointing_down.xml
@@ -19,7 +19,7 @@
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
- android:tint="?attr/colorControlNormal">
+ android:tint="?android:attr/textColorPrimary">
<path
android:fillColor="@android:color/white"
android:pathData="M5.41,7.59L4,9l8,8 8,-8 -1.41,-1.41L12,14.17" />
diff --git a/packages/SystemUI/res/drawable/brightness_bar.xml b/packages/SystemUI/res/drawable/brightness_bar.xml
index 2afe164..3d1c1fb 100644
--- a/packages/SystemUI/res/drawable/brightness_bar.xml
+++ b/packages/SystemUI/res/drawable/brightness_bar.xml
@@ -21,7 +21,7 @@
android:viewportHeight="48">
<path
android:pathData="M2,22L302,22A2,2 0,0 1,304 24L304,24A2,2 0,0 1,302 26L2,26A2,2 0,0 1,0 24L0,24A2,2 0,0 1,2 22z"
- android:fillColor="@color/brightness_slider_track"/>
+ android:fillColor="?androidprv:attr/customColorShadeInactive"/>
<path
android:pathData="M24,0L205.71,0A24,24 0,0 1,229.71 24L229.71,24A24,24 0,0 1,205.71 48L24,48A24,24 0,0 1,0 24L0,24A24,24 0,0 1,24 0z"
android:fillColor="?attr/shadeActive"/>
diff --git a/packages/SystemUI/res/drawable/brightness_progress_drawable.xml b/packages/SystemUI/res/drawable/brightness_progress_drawable.xml
index cae9d6b..ec15b10 100644
--- a/packages/SystemUI/res/drawable/brightness_progress_drawable.xml
+++ b/packages/SystemUI/res/drawable/brightness_progress_drawable.xml
@@ -15,6 +15,7 @@
~ limitations under the License.
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:paddingMode="stack" >
<item android:id="@android:id/background"
android:gravity="center_vertical|fill_horizontal">
@@ -24,7 +25,7 @@
<shape>
<size android:height="@dimen/rounded_slider_track_width" />
<corners android:radius="@dimen/rounded_slider_track_corner_radius" />
- <solid android:color="@color/brightness_slider_track" />
+ <solid android:color="?androidprv:attr/customColorShadeInactive" />
</shape>
</inset>
</item>
diff --git a/packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml b/packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml
index e06bfdc..368fe82 100644
--- a/packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml
+++ b/packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml
@@ -52,7 +52,7 @@
<Button
android:id="@android:id/button1"
style="?android:attr/buttonBarPositiveButtonStyle"
- android:layout_marginStart="8dp"
+ android:layout_marginStart="@dimen/dialog_button_side_margin"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</com.android.internal.widget.ButtonBarLayout>
diff --git a/packages/SystemUI/res/layout/app_clips_screenshot.xml b/packages/SystemUI/res/layout/app_clips_screenshot.xml
index d7b94ec..7b7c96cb 100644
--- a/packages/SystemUI/res/layout/app_clips_screenshot.xml
+++ b/packages/SystemUI/res/layout/app_clips_screenshot.xml
@@ -82,6 +82,23 @@
app:layout_constraintStart_toEndOf="@id/backlinks_include_data"
app:layout_constraintTop_toTopOf="parent" />
+ <TextView
+ android:id="@+id/backlinks_cross_profile_error"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:layout_marginStart="8dp"
+ android:drawablePadding="4dp"
+ android:drawableStart="@drawable/ic_info_outline"
+ android:drawableTint="?androidprv:attr/materialColorOnBackground"
+ android:gravity="center"
+ android:paddingHorizontal="8dp"
+ android:text="@string/backlinks_cross_profile_error"
+ android:textColor="?androidprv:attr/materialColorOnBackground"
+ android:visibility="gone"
+ app:layout_constraintBottom_toTopOf="@id/preview"
+ app:layout_constraintStart_toEndOf="@id/backlinks_data"
+ app:layout_constraintTop_toTopOf="parent" />
+
<ImageView
android:id="@+id/preview"
android:layout_width="0px"
diff --git a/packages/SystemUI/res/layout/notification_template_en_route_contracted.xml b/packages/SystemUI/res/layout/notification_template_en_route_contracted.xml
index 59cfecc..e7a40d1 100644
--- a/packages/SystemUI/res/layout/notification_template_en_route_contracted.xml
+++ b/packages/SystemUI/res/layout/notification_template_en_route_contracted.xml
@@ -16,7 +16,7 @@
<com.android.systemui.statusbar.notification.row.ui.view.EnRouteView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/status_bar_latest_event_content"
+ android:id="@*android:id/status_bar_latest_event_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
diff --git a/packages/SystemUI/res/layout/notification_template_en_route_expanded.xml b/packages/SystemUI/res/layout/notification_template_en_route_expanded.xml
new file mode 100644
index 0000000..ca6d66a
--- /dev/null
+++ b/packages/SystemUI/res/layout/notification_template_en_route_expanded.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2014 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
+ -->
+<com.android.systemui.statusbar.notification.row.ui.view.EnRouteView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@*android:id/status_bar_latest_event_content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:clipChildren="false"
+ android:tag="big"
+ >
+
+ <LinearLayout
+ android:id="@*android:id/notification_action_list_margin_target"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@*android:dimen/notification_content_margin"
+ android:orientation="vertical"
+ >
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_gravity="top"
+ >
+
+ <include layout="@*android:layout/notification_template_header" />
+
+ <LinearLayout
+ android:id="@*android:id/notification_main_column"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@*android:dimen/notification_content_margin_start"
+ android:layout_marginEnd="@*android:dimen/notification_content_margin_end"
+ android:layout_marginTop="@*android:dimen/notification_content_margin_top"
+ android:orientation="vertical"
+ >
+
+ <include layout="@*android:layout/notification_template_part_line1" />
+
+ <include layout="@*android:layout/notification_template_text_multiline" />
+
+ <include
+ android:layout_width="match_parent"
+ android:layout_height="@*android:dimen/notification_progress_bar_height"
+ android:layout_marginTop="@*android:dimen/notification_progress_margin_top"
+ layout="@*android:layout/notification_template_progress"
+ />
+ </LinearLayout>
+
+ <include layout="@*android:layout/notification_template_right_icon" />
+ </FrameLayout>
+
+ <ViewStub
+ android:layout="@*android:layout/notification_material_reply_text"
+ android:id="@*android:id/notification_material_reply_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ />
+
+ <include
+ layout="@*android:layout/notification_template_smart_reply_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@*android:dimen/notification_content_margin_start"
+ android:layout_marginEnd="@*android:dimen/notification_content_margin_end"
+ android:layout_marginTop="@*android:dimen/notification_content_margin"
+ />
+
+ <include layout="@*android:layout/notification_material_action_list" />
+ </LinearLayout>
+</com.android.systemui.statusbar.notification.row.ui.view.EnRouteView>
diff --git a/packages/SystemUI/res/layout/ongoing_activity_chip.xml b/packages/SystemUI/res/layout/ongoing_activity_chip.xml
index 154397d..690a89a 100644
--- a/packages/SystemUI/res/layout/ongoing_activity_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_activity_chip.xml
@@ -17,7 +17,6 @@
the chip. -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/ongoing_activity_chip"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|start"
diff --git a/packages/SystemUI/res/layout/screen_share_dialog.xml b/packages/SystemUI/res/layout/screen_share_dialog.xml
index aa083ad..0533c7e 100644
--- a/packages/SystemUI/res/layout/screen_share_dialog.xml
+++ b/packages/SystemUI/res/layout/screen_share_dialog.xml
@@ -64,30 +64,27 @@
android:layout_height="wrap_content"
android:text="@string/screenrecord_permission_dialog_warning_entire_screen"
style="@style/TextAppearance.Dialog.Body.Message"
- android:gravity="start"/>
+ android:gravity="start"
+ android:textAlignment="gravity"/>
<!-- Buttons -->
<com.android.internal.widget.ButtonBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
- android:layout_marginTop="@dimen/screenrecord_buttons_margin_top">
+ android:layout_marginTop="@dimen/screenrecord_buttons_margin_top"
+ android:gravity="end">
<Button
android:id="@android:id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_weight="0"
android:text="@string/cancel"
style="@style/Widget.Dialog.Button.BorderButton" />
- <Space
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"/>
<Button
android:id="@android:id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_weight="0"
+ android:layout_marginStart="@dimen/dialog_button_side_margin"
android:text="@string/screenrecord_continue"
style="@style/Widget.Dialog.Button" />
</com.android.internal.widget.ButtonBarLayout>
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 4247c7e..541aebe 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -66,7 +66,7 @@
<FrameLayout
android:id="@+id/status_bar_start_side_content"
android:layout_width="wrap_content"
- android:layout_height="match_parent"
+ android:layout_height="wrap_content"
android:layout_gravity="center_vertical|start"
android:clipChildren="false">
@@ -99,7 +99,10 @@
android:gravity="center_vertical|start"
/>
- <include layout="@layout/ongoing_activity_chip" />
+ <include layout="@layout/ongoing_activity_chip"
+ android:id="@+id/ongoing_activity_chip_primary"/>
+
+ <!-- TODO(b/364653005): Add a second activity chip. -->
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
android:id="@+id/notification_icon_area"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 7251f03..2a669de 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> en ander oop apps het hierdie skermskoot bespeur."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Voeg by nota"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Sluit skakel in"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Skermopnemer"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Verwerk tans skermopname"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Deurlopende kennisgewing vir \'n skermopnamesessie"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Sluimerskerm"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Moenie Steur Nie"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioriteitmodusse"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Geen saamgebinde toestelle beskikbaar nie"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tik om ’n toestel te koppel of ontkoppel"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Gebruik Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Gekoppel"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Oudiodeling"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tik om oor te skakel of oudio te deel"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gestoor"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ontkoppel"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiveer"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Maak Instellings oop"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Ander toestel"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Wissel oorsig"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriteitmodusse"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Klaar"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Instellings"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Aan"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Die diens wat hierdie funksie verskaf, sal toegang hê tot al die inligting wat op jou skerm sigbaar is of op jou toestel gespeel word terwyl dit opneem of uitsaai. Dit sluit in inligting soos wagwoorde, betalingbesonderhede, foto’s, boodskappe en oudio wat jy speel."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Deel of neem ’n app op"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Deel jou skerm met <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Deel een app"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Deel hele skerm"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Deel een app"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Deel hele skerm"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Wanneer jy jou hele skerm deel, is enigiets op jou skerm sigbaar aan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Wanneer jy ’n app deel, is enigiets wat in die app wys of speel, sigbaar aan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Deel skerm"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliet, goeie toestand"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliet, verbinding is beskikbaar"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelliet-SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Noodoproepe of SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Werkprofiel"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Pret vir party mense, maar nie vir almal nie"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Stelsel-UI-ontvanger gee jou ekstra maniere om die Android-gebruikerkoppelvlak in te stel en te pasmaak. Hierdie eksperimentele kenmerke kan in toekomstige uitreikings verander, breek of verdwyn. Gaan versigtig voort."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Vou ikoon in"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Vou ikoon uit"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"of"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Teruggebaar"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Tuisgebaar"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Handelingsleutel"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 54fb216d..f7f9763 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> እና ሌሎች ክፍት መተግበሪያዎች ይህን ቅጽበታዊ ገፅ ዕይታ ለይተዋል።"</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"ወደ ማስታወሻ አክል"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"አገናኝ አካትት"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g><xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"የማያ መቅረጫ"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"የማያ ገፅ ቀረጻን በማሰናዳት ላይ"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ለአንድ የማያ ገፅ ቀረጻ ክፍለ-ጊዜ በመካሄድ ያለ ማሳወቂያ"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"የማያ ገፅ ማቆያ"</string>
<string name="ethernet_label" msgid="2203544727007463351">"ኤተርኔት"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"አትረብሽ"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"ቅድሚያ ሁነታዎች"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ብሉቱዝ"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ምንም የተጣመሩ መሣሪያዎች አይገኝም"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"መሣሪያን ለማገናኘት ወይም ግንኙነቱን ለማቋረጥ መታ ያድርጉ"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ብሉቱዝን ይጠቀሙ"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ተገናኝቷል"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"የድምጽ ማጋራት"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ኦዲዮ ለመቀየር ወይም ለማጋራት መታ ያድርጉ"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ተቀምጧል"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ግንኙነትን አቋርጥ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ያግብሩ"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"ቅንብሮችን ክፈት"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"ሌላ መሣሪያ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"አጠቃላይ እይታን ቀያይር"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ቅድሚያ ሁነታዎች"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"ተከናውኗል"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ቅንብሮች"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"በርቷል"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ይህን ተግባር የሚያቀርበው አገልግሎት በእርስዎ ማያ ገጽ ላይ ለሚታየው ወይም በሚቀረጽበት ወይም cast በሚደረግበት ጊዜ በእርስዎ መሣሪያ ላይ ለሚጫወተው ሁሉም መረጃ መዳረሻ ይኖረዋል። ይህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ ፎቶዎች፣ መልዕክቶች እና እርስዎ የሚያጫውቱትን ኦዲዮ የመሳሰለ መረጃን ያካትታል።"</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"መተግበሪያን ያጋሩ ወይም ይቅረጹ"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"ማያ ገፅዎን ለ<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ያጋራሉ?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"አንድ መተግበሪያ ያጋሩ"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"መላውን ማያ ገፅ ያጋሩ"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"አንድ መተግበሪያ ያጋሩ"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"መላውን ማያ ገፅ ያጋሩ"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"እርስዎ ሙሉ ማያ ገፅዎን ሲያጋሩ በማያ ገፅዎ ላይ ያለው ማንኛውም ነገር ለ<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ይታያል። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"መተግበሪያን ሲያጋሩ በዚያ መተግበሪያ ውስጥ የሚታይ ወይም የሚጫወት ማንኛውም ነገር ለ<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ይታያል። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"ማያ ገፅ አጋራ"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ሳተላይት፣ ጥሩ ግንኙነት"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ሳተላይት፣ ግንኙነት አለ"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"ሳተላይት ኤስኦኤስ"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"የአደጋ ጥሪዎች ወይም ኤስኦኤስ"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"የስራ መገለጫ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ለአንዳንዶች አስደሳች ቢሆንም ለሁሉም አይደለም"</string>
<string name="tuner_warning" msgid="1861736288458481650">"የስርዓት በይነገጽ መቃኛ የAndroid ተጠቃሚ በይነገጹን የሚነካኩበት እና የሚያበጁበት ተጨማሪ መንገዶች ይሰጠዎታል። እነዚህ የሙከራ ባህሪዎች ወደፊት በሚኖሩ ልቀቶች ላይ ሊለወጡ፣ ሊሰበሩ ወይም ሊጠፉ ይችላሉ። ከጥንቃቄ ጋር ወደፊት ይቀጥሉ።"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"መሰብሰቢያ አዶ"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"መዘርጊያ አዶ"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ወይም"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"የተመለስ ምልክት"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"የቤት ምልክት"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"የተግባር ቁልፍ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 6866ed7..5d6b908 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"رصَد تطبيق \"<xliff:g id="APPNAME">%1$s</xliff:g>\" والتطبيقات المفتوحة الأخرى لقطة الشاشة هذه."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"إضافة إلى الملاحظة"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"تضمين الرابط"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"مسجّل الشاشة"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"جارٍ معالجة تسجيل الشاشة"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"إشعار مستمر لجلسة تسجيل شاشة"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"شاشة الاستراحة"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"عدم الإزعاج"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"الأوضاع ذات الأولوية"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"بلوتوث"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"لا يتوفر أي أجهزة مقترنة"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"انقر للاتصال بجهاز أو قطع الاتصال به"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"استخدام البلوتوث"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"متّصل"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"مشاركة الصوت"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"انقر لتبديل مصدر الصوت أو مشاركته"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"محفوظ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"إلغاء الربط"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"تفعيل"</string>
@@ -384,13 +387,13 @@
<string name="qs_record_issue_start" msgid="2979831312582567056">"بدء"</string>
<string name="qs_record_issue_stop" msgid="3531747965741982657">"إيقاف"</string>
<string name="qs_record_issue_bug_report" msgid="8229031766918650079">"تقرير خطأ"</string>
- <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"ما هو الجانب الذي تأثّر في تجربة استخدام الجهاز؟"</string>
+ <string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"بأي جانب من تجربة استخدام الجهاز تتعلّق المشكلة؟"</string>
<string name="qs_record_issue_dropdown_prompt" msgid="2526949919167046219">"اختيار نوع المشكلة"</string>
<string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"تسجيل الشاشة"</string>
<string name="performance" msgid="6552785217174378320">"الأداء"</string>
<string name="user_interface" msgid="3712869377953950887">"واجهة المستخدم"</string>
- <string name="thermal" msgid="6758074791325414831">"الأداء الحراري"</string>
- <string name="custom" msgid="3337456985275158299">"مخصّص"</string>
+ <string name="thermal" msgid="6758074791325414831">"ارتفاع حرارة الجهاز"</string>
+ <string name="custom" msgid="3337456985275158299">"الإعدادات المخصّصة"</string>
<string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"إعدادات التتبع المخصصة"</string>
<string name="restore_default" msgid="5259420807486239755">"استعادة الإعدادات التلقائية"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"وضع \"التصفح بيد واحدة\""</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"فتح الإعدادات"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"جهاز آخر"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"تبديل \"النظرة العامة\""</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"الأوضاع ذات الأولوية"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"تم"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"الإعدادات"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"مفعَّل"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ستتمكن الخدمة التي تقدّم هذه الوظيفة من الوصول إلى كل المحتوى المعروض على شاشتك أو الذي يتم تشغيله على جهازك أثناء التسجيل أو البثّ. ويشمل ذلك معلومات، مثل كلمات المرور وتفاصيل الدفع والصور والرسائل والمقاطع الصوتية التي تشغِّلها."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"مشاركة محتوى تطبيق أو تسجيله"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"هل تريد مشاركة الشاشة مع تطبيق \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\"؟"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"مشاركة تطبيق واحد"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"مشاركة الشاشة بأكملها"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"مشاركة تطبيق واحد"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"مشاركة الشاشة بأكملها"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"أثناء مشاركة محتوى الشاشة بالكامل، سيكون كل المحتوى المعروض على شاشتك مرئيًا لتطبيق \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\". لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"أثناء مشاركة محتوى تطبيق، سيكون كل المحتوى المعروض أو الذي يتم تشغيله في ذلك التطبيق مرئيًا لتطبيق \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\". لذا يُرجى توخي الحذر بشأن المعلومات، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور وملفات الصوت والفيديو."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"مشاركة الشاشة"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"قمر صناعي، الاتصال جيد"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"قمر صناعي، الاتصال متوفّر"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"اتصالات الطوارئ بالقمر الصناعي"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"مكالمات الطوارئ أو ميزة \"اتصالات طوارئ بالقمر الصناعي\""</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ملف العمل"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"متعة للبعض وليس للجميع"</string>
<string name="tuner_warning" msgid="1861736288458481650">"توفر لك أداة ضبط واجهة مستخدم النظام طرقًا إضافية لتعديل واجهة مستخدم Android وتخصيصها. ويمكن أن تطرأ تغييرات على هذه الميزات التجريبية أو يمكن أن تتعطل هذه الميزات أو تختفي في الإصدارات المستقبلية. عليك متابعة الاستخدام مع توخي الحذر."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"رمز التصغير"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"رمز التوسيع"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"أو"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"إيماءة الرجوع"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"إيماءة الانتقال إلى الشاشة الرئيسية"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"مفتاح الإجراء"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 0c8ef43..2e8a552 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> আৰু আন খোলা এপ্সমূহে এই স্ক্ৰীনশ্বটটো চিনাক্ত কৰিছে।"</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"টোকাত যোগ দিয়ক"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"লিংক অন্তৰ্ভুক্ত কৰক"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"স্ক্ৰীন ৰেকৰ্ডাৰ"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"স্ক্রীন ৰেকৰ্ডিঙৰ প্ৰক্ৰিয়াকৰণ হৈ আছে"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রীন ৰেকৰ্ডিং ছেশ্বন চলি থকা সময়ত পোৱা জাননী"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"স্ক্ৰীন ছেভাৰ"</string>
<string name="ethernet_label" msgid="2203544727007463351">"ইথাৰনেট"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"অসুবিধা নিদিব"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"অগ্ৰাধিকাৰপ্ৰাপ্ত ম’ড"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ব্লুটুথ"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"কোনো যোৰা লগোৱা ডিভাইচ উপলব্ধ নহয়।"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"ডিভাইচ সংযোগ কৰিবলৈ অথবা সংযোগ বিচ্ছিন্ন কৰিবলৈ টিপক"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ব্লুটুথ ব্যৱহাৰ কৰক"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"সংযুক্ত আছে"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"অডিঅ’ শ্বেয়াৰ কৰা"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"অডিঅ’ সলনি কৰিবলৈ বা শ্বেয়াৰ কৰিলৈ টিপক"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ছেভ কৰা হৈছে"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"সংযোগ বিচ্ছিন্ন কৰক"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"সক্ৰিয় কৰক"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"ছেটিং খোলক"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"অন্য ডিভাইচ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"অৱলোকন ট’গল কৰক"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"অগ্ৰাধিকাৰপ্ৰাপ্ত ম’ডসমূহ"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"কৰা হ’ল"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ছেটিং"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"অন আছে"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"এই সুবিধাটো প্ৰদান কৰা সেৱাটোৱে আপোনাৰ স্ক্ৰীনত দৃশ্যমান হোৱা অথবা ৰেকৰ্ডিং অথবা কাষ্টিঙৰ সময়ত আপোনাৰ ডিভাইচত প্লে’ কৰা আটাইবোৰ তথ্যলৈ এক্সেছ পাব। এইটোত পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, ফট’, বাৰ্তাসমূহ আৰু আপুনি প্লে’ কৰা অডিঅ’ৰ দৰে তথ্য অন্তৰ্ভুক্ত হয়।"</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"এটা এপ্ শ্বেয়াৰ অথবা ৰেকৰ্ড কৰক"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ৰ সৈতে আপোনাৰ স্ক্ৰীন শ্বেয়াৰ কৰিবনে?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"এটা এপ্ শ্বেয়াৰ কৰক"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"গোটেই স্ক্ৰীনখন শ্বেয়াৰ কৰক"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"এটা এপ্ শ্বেয়াৰ কৰক"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"গোটেই স্ক্ৰীনখন শ্বেয়াৰ কৰক"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"আপুনি আপোনাৰ গোটেই স্ক্ৰীনখন শ্বেয়াৰ কৰি থাকোঁতে, আপোনাৰ স্ক্ৰীনত থকা যিকোনো বস্তু <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ত দৃশ্যমান হয়। সেয়ে পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"আপুনি কোনো এপ্ শ্বেয়াৰ কৰি থাকোঁতে সেই এপ্টোত দেখুওৱা বা প্লে’ কৰা যিকোনো বস্তু <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ত দৃশ্যমান হয়। সেয়ে পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"স্ক্ৰীন শ্বেয়াৰ কৰক"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"উপগ্ৰহ, ভাল সংযোগ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"উপগ্ৰহ, সংযোগ উপলব্ধ"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"উপগ্ৰহ SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"জৰুৰীকালীন কল বা SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"কিছুমানৰ বাবে আমোদজনক হয় কিন্তু সকলোৰে বাবে নহয়"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tunerএ আপোনাক Android ব্যৱহাৰকাৰী ইণ্টাৰফেইচ সলনি কৰিবলৈ আৰু নিজৰ উপযোগিতা অনুসৰি ব্যৱহাৰ কৰিবলৈ অতিৰিক্ত সুবিধা প্ৰদান কৰে। এই পৰীক্ষামূলক সুবিধাসমূহ সলনি হ\'ব পাৰে, সেইবোৰে কাম নকৰিব পাৰে বা আগন্তুক সংস্কৰণসমূহত সেইবোৰ অন্তৰ্ভুক্ত কৰা নহ’ব পাৰে। সাৱধানেৰে আগবাঢ়ক।"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"সংকোচন কৰাৰ চিহ্ন"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"বিস্তাৰ কৰাৰ চিহ্ন"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"অথবা"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"উভতি যাওক নিৰ্দেশ"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"গৃহ স্ক্ৰীনলৈ যোৱাৰ নিৰ্দেশ"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"কাৰ্য কী"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index df3ecf7..b011ca64 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> və digər açıq tətbiqlər bu skrinşotu aşkarladı."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Qeydə əlavə edin"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Keçid daxil edin"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g><xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Ekran yazıcısı"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran çəkilişi emal edilir"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekranın video çəkimi ərzində silinməyən bildiriş"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Ekran qoruyucu"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Narahat etməyin"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioritet rejimləri"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Heç bir cütlənmiş cihaz əlçatan deyil"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Toxunaraq cihaza qoşulun, yaxud əlaqəni ayırın"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth-u açın"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Qoşulub"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio paylaşma"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Dəyişmək və ya audio paylaşmaq üçün toxunun"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Yadda saxlandı"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"əlaqəni kəsin"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivləşdirin"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Ayarları açın"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Digər cihaz"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"İcmala Keçin"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritet rejimləri"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Hazırdır"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ayarlar"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Aktiv"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Bu funksiyanı təmin edən xidmətin qeydəalma və ya yayım zamanı ekranda görünən, yaxud cihazda oxudulan məlumatlara girişi olacaq. Bura parol, ödəniş detalları, foto, mesaj və oxudulan audio kimi məlumatlar daxildir."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Tətbiq paylaşın və ya qeydə alın"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Ekran <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ilə paylaşılsın?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Bir tətbiq paylaşın"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Bütün ekranı paylaşın"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Bir tətbiq paylaşın"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Bütün ekranı paylaşın"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Bütün ekranı paylaşdığınız zaman ekrandakı hər şey <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> üçün görünən olacaq. Parol, ödəniş məlumatı, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Tətbiq paylaşdığınız zaman həmin tətbiqdə göstərilən və ya işə salınan hər şey <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> üçün görünən olacaq. Parol, ödəniş məlumatı, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ekranı paylaşın"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Peyk, bağlantı yaxşıdır"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Peyk, bağlantı var"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Təcili peyk bağlantısı"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Təcili zənglər və ya SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"İş profili"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Hamı üçün deyil, bəziləri üçün əyləncəli"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner Android istifadəçi interfeysini dəyişdirmək və fərdiləşdirmək üçün Sizə ekstra yollar təklif edir."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"İkonanı yığcamlaşdırın"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"İkonanı genişləndirin"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"və ya"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Geri jesti"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Əsas ekran jesti"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Əməliyyat düyməsi"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 9198710..c581fd5 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> i druge otvorene aplikacije su otkrile ovaj snimak ekrana."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Dodaj u belešku"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Uvrsti link"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Snimač ekrana"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrađujemo video snimka ekrana"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Obaveštenje o sesiji snimanja ekrana je aktivno"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Čuvar ekrana"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Eternet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ne uznemiravaj"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioritetni režimi"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Nije dostupan nijedan upareni uređaj"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Dodirnite da biste povezali uređaj ili prekinuli vezu"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Koristi Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Povezano"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Deljenje zvuka"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Dodirnite da biste prebacili ili delili zvuk"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Sačuvano"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekinite vezu"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivirajte"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Otvori Podešavanja"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Drugi uređaj"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Uključi/isključi pregled"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritetni režimi"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gotovo"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Podešavanja"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Uključeno"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Usluga koja pruža ovu funkciju će imati pristup svim informacijama koje se prikazuju na ekranu ili reprodukuju sa uređaja tokom snimanja ili prebacivanja. To obuhvata informacije poput lozinki, informacija o plaćanju, slika, poruka i zvuka koji puštate."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Delite ili snimite aplikaciju"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Želite da delite ekran sa aplikacijom <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Deli jednu aplikaciju"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Deli ceo ekran"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Deli jednu aplikaciju"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Deli ceo ekran"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kada delite ceo ekran, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vidi sve što je na njemu. Zato pazite na lozinke, informacije o plaćanju, poruke, slike, audio i video sadržaj."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kada delite aplikaciju, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vidi sav sadržaj koji se prikazuje ili pušta u njoj. Zato pazite na lozinke, informacije o plaćanju, poruke, slike, audio i video sadržaj."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Deli ekran"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, veza je dobra"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, veza je dostupna"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Hitna pomoć preko satelita"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Hitni pozivi ili hitna pomoć"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Poslovni profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Tjuner za korisnički interfejs sistema vam pruža dodatne načine za podešavanje i prilagođavanje Android korisničkog interfejsa. Ove eksperimentalne funkcije mogu da se promene, otkažu ili nestanu u budućim izdanjima. Budite oprezni."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona za skupljanje"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona za proširivanje"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ili"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Pokret za vraćanje"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Pokret za početnu stranicu"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Taster radnji"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index c5c2912..31854f6 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> і іншыя адкрытыя праграмы выявілі гэты здымак экрана."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Дадаць у нататку"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Дадаць спасылку"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Запіс экрана"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Апрацоўваецца запіс экрана"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Бягучае апавяшчэнне для сеанса запісу экрана"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Экранная застаўка"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Не турбаваць"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Прыярытэтныя рэжымы"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Няма даступных спалучаных прылад"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Націсніце, каб падключыць або адключыць прыладу"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Выкарыстоўваць Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Падключана"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Абагульванне аўдыя"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Націсніце, каб пераключыць або абагуліць аўдыя"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Захавана"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"адключыць"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"актываваць"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Адкрыць налады"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Іншая прылада"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Уключыць/выключыць агляд"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Прыярытэтныя рэжымы"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Гатова"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Налады"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Уключана"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Падчас запісу ці трансляцыі служба, якая забяспечвае работу гэтай функцыі, будзе мець доступ да ўсёй інфармацыі, адлюстраванай на экране вашай прылады, ці той, якая праз яе прайграецца. Гэтая інфармацыя ўключае паролі, плацежных рэквізітаў, фота, паведамленні і аўдыя, якое вы прайграяце."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Абагульванне або запіс праграмы"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Абагуліць экран з праграмай \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\"?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Абагуліць адну праграму"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Абагуліць увесь экран"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Абагуліць адну праграму"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Абагуліць увесь экран"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Калі вы абагульваеце ўвесь экран, праграма \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" можа бачыць усё, што адбываецца на экране. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Калі вы абагульваеце праграму, праграма \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\" можа бачыць усё, што паказваецца ці прайграецца ў гэтай праграме. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Абагуліць экран"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Спадарожнікавая сувязь, добрае падключэнне"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Спадарожнікавая сувязь, падключэнне даступнае"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Экстраннае спадарожнікавае падключэнне"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Экстранныя выклікі або экстраннае спадарожнікавае падключэнне"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Працоўны профіль"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Цікава для некаторых, але не для ўсіх"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Наладка сістэмнага інтэрфейсу карыстальніка дае вам дадатковыя спосабы наладжвання і дапасоўвання карыстальніцкага інтэрфейсу Android. Гэтыя эксперыментальныя функцыі могуць змяніцца, перастаць працаваць або знікнуць у будучых версіях. Карыстайцеся з асцярожнасцю."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Значок \"Згарнуць\""</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Значок \"Разгарнуць\""</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"або"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Жэст для вяртання на папярэдні экран"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Жэст для вяртання на галоўны экран"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Клавіша дзеяння"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 58f492e..64ecfd3 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> и други отворени приложения установиха заснемането на тази екранна снимка."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Добавяне към бележката"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Включване на връзката"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Запис на екрана"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Записът на екрана се обработва"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущо известие за сесия за записване на екрана"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Скрийнсейвър"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Не безпокойте"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Приоритетни режими"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Няма налични сдвоени устройства"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Докоснете, за да свържете устройство или да прекъснете връзката му"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Използване на Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Установена е връзка"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Споделяне на звука"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Докоснете, за да превключите или споделите аудио"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Запазено"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"прекратяване на връзката"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активиране"</string>
@@ -390,7 +393,7 @@
<string name="performance" msgid="6552785217174378320">"Ефективност"</string>
<string name="user_interface" msgid="3712869377953950887">"Потребителски интерфейс"</string>
<string name="thermal" msgid="6758074791325414831">"Температура"</string>
- <string name="custom" msgid="3337456985275158299">"Персонализирано"</string>
+ <string name="custom" msgid="3337456985275158299">"Персонализиране"</string>
<string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Настройки за персонализираната следа"</string>
<string name="restore_default" msgid="5259420807486239755">"Възстановяване на стандартната настройка"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Режим за работа с една ръка"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Към настройките"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Друго устройство"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Превключване на общия преглед"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Приоритетни режими"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Настройки"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Вкл."</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Услугата, предоставяща тази функция, ще има достъп до цялата информация, която е видима на екрана или възпроизвеждана от устройството ви по време на записване или предаване. Това включва различна информация, като например пароли, подробности за начини на плащане, снимки, съобщения и възпроизвеждано аудио."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Споделяне или записване на приложение"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Да се сподели ли екранът ви с(ъс) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Споделяне на едно приложение"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Споделяне на целия екран"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Споделяне на едно приложение"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Споделяне на целия екран"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Когато споделяте целия си екран, всичко, което се показва на него, е видимо за <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Когато споделяте приложение, всичко, което се показва или възпроизвежда в него, е видимо за <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Споделяне на екрана"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Сателит, добра връзка"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Сателит, налице е връзка"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS чрез сателит"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Спешни обаждания или SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Потребителски профил в Work"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Забавно – но не за всички"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Тунерът на системния потребителски интерфейс ви предоставя допълнителни възможности за прецизиране и персонализиране на практическата работа с Android. Тези експериментални функции може да се променят, повредят или да изчезнат в бъдещите версии. Действайте внимателно."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Икона за свиване"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Икона за разгъване"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"или"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Жест за връщане назад"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Жест за преминаване към началния екран"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Клавиш за действия"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index c9e24f0..f62ee9e 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> এবং খোলা থাকা অন্য অ্যাপ এই স্ক্রিনশট শনাক্ত করেছে।"</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"নোটে যোগ করুন"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"লিঙ্ক যোগ করুন"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"স্ক্রিন রেকর্ডার"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"স্ক্রিন রেকর্ডিং প্রসেস হচ্ছে"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রিন রেকর্ডিং সেশন চলার বিজ্ঞপ্তি"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"স্ক্রিন সেভার"</string>
<string name="ethernet_label" msgid="2203544727007463351">"ইথারনেট"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"বিরক্ত করবে না"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"প্রায়োরিটি মোড"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ব্লুটুথ"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"চেনা কোনও ডিভাইস নেই"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"কোনও ডিভাইস কানেক্ট বা ডিসকানেক্ট করতে ট্যাপ করুন"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ব্লুটুথ ব্যবহার করুন"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"কানেক্ট করা আছে"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"অডিও শেয়ারিং"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"অডিও শেয়ার বা পরিবর্তন করতে ট্যাপ করুন"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"সেভ করা আছে"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ডিসকানেক্ট করুন"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"চালু করুন"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"সেটিংস খুলুন"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"অন্য ডিভাইস"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"\'এক নজরে\' বৈশিষ্ট্যটি চালু বা বন্ধ করুন"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"প্রায়োরিটি মোড"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"হয়ে গেছে"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"সেটিংস"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"চালু আছে"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"যে পরিষেবা এই ফাংশন প্রদান করছে, সেটি রেকর্ড বা কাস্ট করার সময় আপনার স্ক্রিনে দৃশ্যমান বা ডিভাইসে চালানো হয়েছে এমন সব তথ্য অ্যাক্সেস করতে পারবে। এর মধ্যে আপনার পাসওয়ার্ড, পেমেন্টের বিবরণ, ফটো, মেসেজ এবং আপনার চালানো অডিও সম্পর্কিত তথ্য রয়েছে।"</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"কোনও অ্যাপ শেয়ার বা রেকর্ড করুন"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-এর সাথে আপনার স্ক্রিন শেয়ার করবেন?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"একটি অ্যাপ শেয়ার করুন"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"সম্পূর্ণ স্ক্রিন শেয়ার করুন"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"একটি অ্যাপ শেয়ার করুন"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"সম্পূর্ণ স্ক্রিন শেয়ার করুন"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"আপনার সম্পূর্ণ স্ক্রিন শেয়ার করার সময়, স্ক্রিনে থাকা সব কিছু <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> দেখতে পাবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ের ক্ষেত্রে সতর্ক থাকুন।"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"কোনও অ্যাপ শেয়ার করার সময়, সেই অ্যাপে দেখা ও চালানো হয় এমন সব কিছু <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> দেখতে পাবে। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ের ক্ষেত্রে সতর্ক থাকুন।"</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"স্ক্রিন শেয়ার করুন"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"স্যাটেলাইট, ভালো কানেকশন"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"স্যাটেলাইট, কানেকশন উপলভ্য আছে"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"স্যাটেলাইট SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"জরুরি কল বা SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"কাজের প্রোফাইল"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"কিছু ব্যক্তির জন্য মজাদার কিন্তু সকলের জন্য নয়"</string>
<string name="tuner_warning" msgid="1861736288458481650">"এই পরীক্ষামূলক বৈশিষ্ট্যগুলি ভবিষ্যতের সংস্করণগুলির মধ্যে পরিবর্তিত, বিভাজিত এবং অদৃশ্য হয়ে যেতে পারে৷ সাবধানতার সাথে এগিয়ে যান৷ সিস্টেম UI টিউনার আপনাকে Android ব্যবহারকারী ইন্টারফেসের সূক্ষ্ম সমন্বয় এবং কাস্টমাইজ করার অতিরিক্ত উপায়গুলি প্রদান করে৷"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"আইকন আড়াল করুন"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"আইকন বড় করুন"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"অথবা"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ফিরে যাওয়ার জেসচার"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"হোমপেজে যাওয়ার জেসচার"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"অ্যাকশন কী"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 8949567..51416ef 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Aplikacija <xliff:g id="APPNAME">%1$s</xliff:g> i druge otvorene aplikacije su otkrile ovaj snimak ekrana."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Dodaj u bilješku"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Uključi link"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Snimač ekrana"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrađivanje snimka ekrana"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Obavještenje za sesiju snimanja ekrana je u toku"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Čuvar ekrana"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ne ometaj"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioritetni načini rada"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Nema dostupnih uparenih uređaja"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Dodirnite da povežete ili prekinete povezanost uređaja"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Koristi Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Povezano"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Dijeljenje zvuka"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Dodirnite da uključite ili dijelite zvučni zapis"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Sačuvano"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekid veze"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiviranje"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Otvori Postavke"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Drugi uređaj"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Pregled uključivanja/isključivanja"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritetni načini rada"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gotovo"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Postavke"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Uključeno"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Usluga koja pruža ovu funkciju će imati pristup svim informacijama koje su vidljive na ekranu ili koje se reproduciraju s uređaja tokom snimanja ili emitiranja. To uključuje informacije kao što su lozinke, detalji o plaćanju, fotografije, poruke i zvuk koji reproducirate."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Dijelite ili snimajte aplikaciju"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Dijeliti ekran s aplikacijom <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Dijeli jednu aplikaciju"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Dijeli cijeli ekran"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Dijeli jednu aplikaciju"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Dijeli cijeli ekran"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kada dijelite cijeli ekran, sve što je na ekranu će biti vidljivo aplikaciji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kada dijelite aplikaciju, sve što se prikazuje ili reproducira u toj aplikaciji će biti vidljivo aplikaciji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, zvukovi i videozapisi."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Dijeli ekran"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobra veza"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, veza je dostupna"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Hitna pomoć putem satelita"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Hitni pozivi ili pomoć"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Radni profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Podešavač za korisnički interfejs sistema vam omogućava dodatne načine da podesite i prilagodite Androidov interfejs. Ove eksperimentalne funkcije se u budućim verzijama mogu mijenjati, kvariti ili nestati. Budite oprezni."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona sužavanja"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona proširivanja"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ili"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Pokret za povratak"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Pokret za povratak na početni ekran"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tipka radnji"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 74cce98..182fe02 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -104,13 +104,14 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> i altres aplicacions obertes han detectat aquesta captura de pantalla."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Afegeix a una nota"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Inclou l\'enllaç"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Gravació de pantalla"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processant gravació de pantalla"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificació en curs d\'una sessió de gravació de la pantalla"</string>
<string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Vols gravar la pantalla?"</string>
<string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Grava una aplicació"</string>
<string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="2794896384693120020">"Grava tota la pantalla"</string>
- <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Quan graves tota la pantalla, es grava tot el que es mostra en pantalla. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos, i l\'àudio i el vídeo."</string>
+ <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Quan graves tota la pantalla, es grava tot el que es mostra en pantalla. Per aquest motiu, ves amb compte amb elements com les contrasenyes, les dades de pagament, els missatges, les fotos, i l\'àudio i el vídeo."</string>
<string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Quan graves una aplicació, es grava tot el que es mostra o es reprodueix en aquesta aplicació. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos, i l\'àudio i el vídeo."</string>
<string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Grava la pantalla"</string>
<string name="screenrecord_app_selector_title" msgid="3854492366333954736">"Tria una aplicació per gravar"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Estalvi de pantalla"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"No molestis"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modes prioritaris"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"No hi ha dispositius vinculats disponibles"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Toca per connectar o desconnectar un dispositiu"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Utilitza el Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connectat"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Compartició d\'àudio"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Toca per canviar o compartir l\'àudio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Desat"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconnecta"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activa"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Obre Configuració"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Un altre dispositiu"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activa o desactiva Aplicacions recents"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modes prioritaris"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Fet"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configuració"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Activat"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"El servei que ofereix aquesta funció tindrà accés a tota la informació visible a la teva pantalla o que es reprodueix al dispositiu mentre graves o emets contingut, com ara les contrasenyes, les dades de pagament, les fotos, els missatges i àudio que reprodueixis."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Comparteix o grava una aplicació"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Vols compartir la pantalla amb <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Comparteix una aplicació"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Comparteix tota la pantalla"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Comparteix una aplicació"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Comparteix tota la pantalla"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Quan comparteixes tota la pantalla, qualsevol cosa que es mostra en pantalla és visible a <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos i l\'àudio i el vídeo."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Quan comparteixes una aplicació, qualsevol cosa que es mostra o que es reprodueix en aquesta aplicació és visible a <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos i l\'àudio i el vídeo."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Comparteix la pantalla"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satèl·lit, bona connexió"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satèl·lit, connexió disponible"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS per satèl·lit"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Trucades d\'emergència o SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de treball"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversió per a uns quants, però no per a tothom"</string>
<string name="tuner_warning" msgid="1861736288458481650">"El Personalitzador d\'interfície d\'usuari presenta opcions addicionals per canviar i personalitzar la interfície d\'usuari d\'Android. És possible que aquestes funcions experimentals canviïn, deixin de funcionar o desapareguin en versions futures. Continua amb precaució."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Replega la icona"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Desplega la icona"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"o"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gest Enrere"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gest Inici"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla d\'acció"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 8c0571e..cebb175 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> a ostatní otevřené aplikace objevily tento snímek obrazovky."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Přidat do poznámky"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Zahrnout odkaz"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Nahrávání obrazovky"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Záznam obrazovky se zpracovává"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Trvalé oznámení o relaci nahrávání"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Spořič obrazovky"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Nerušit"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Režimy priority"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Nejsou dostupná žádná spárovaná zařízení"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Klepnutím zařízení připojíte nebo odpojíte"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Používat Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Připojeno"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Sdílení zvuku"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Klepnutím přepnete nebo nasdílíte zvuk"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Uloženo"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"odpojit"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivovat"</string>
@@ -389,7 +392,7 @@
<string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Záznam obrazovky"</string>
<string name="performance" msgid="6552785217174378320">"Výkon"</string>
<string name="user_interface" msgid="3712869377953950887">"Uživatelské rozhraní"</string>
- <string name="thermal" msgid="6758074791325414831">"Termovize"</string>
+ <string name="thermal" msgid="6758074791325414831">"Teplota"</string>
<string name="custom" msgid="3337456985275158299">"Vlastní"</string>
<string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Vlastní nastavení trasování"</string>
<string name="restore_default" msgid="5259420807486239755">"Obnovit výchozí"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Otevřít nastavení"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Další zařízení"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Přepnout přehled"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Režimy priority"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Hotovo"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nastavení"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Zapnuto"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Služba, která tuto funkci poskytuje, bude mít při nahrávání nebo odesílání přístup ke všem informacím, které jsou viditelné na obrazovce nebo které jsou přehrávány ze zařízení. Týká se to i hesel, údajů o platbě, fotek, zpráv a přehrávaných zvuků."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Sdílení nebo nahrání aplikace"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Sdílet obrazovku s aplikací <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Sdílet jednu aplikaci"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Sdílet celou obrazovku"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Sdílet jednu aplikaci"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Sdílet celou obrazovku"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Při sdílení celé obrazovky vidí aplikace <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vše, co se na obrazovce nachází nebo děje. Buďte proto opatrní s věcmi, jako jsou hesla, platební údaje, zprávy, fotografie, zvuk a video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Při sdílení aplikace vidí aplikace <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vše, co se ve sdílené aplikaci nachází nebo děje. Buďte proto opatrní s věcmi, jako jsou hesla, platební údaje, zprávy, fotografie, zvuk a video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Sdílet obrazovku"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobré připojení"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, připojení je k dispozici"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS přes satelit"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Tísňová volání nebo SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Pracovní profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zábava, která není pro každého"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Nástroj na ladění uživatelského rozhraní systému vám nabízí další způsoby, jak si vyladit a přizpůsobit uživatelské rozhraní Android. Tyto experimentální funkce mohou v dalších verzích chybět, nefungovat nebo být změněny. Postupujte proto prosím opatrně."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona sbalení"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona rozbalení"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"nebo"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto zpět"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto domů"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Akční klávesa"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 9b72478..974083e 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> og andre åbne apps har registreret dette screenshot."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Føj til note"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Inkluder link"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Skærmoptagelse"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandler skærmoptagelse"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Konstant notifikation om skærmoptagelse"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Pauseskærm"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Forstyr ikke"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Tilstande med prioritet"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Der er ingen tilgængelige parrede enheder"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tryk for at oprette eller afbryde forbindelse til en enhed"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Brug Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Der er oprettet forbindelse"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Lyddeling"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tryk for at skifte eller dele lyd"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gemt"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"afbryd forbindelse"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivér"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Åbn Indstillinger"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Anden enhed"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Slå Oversigt til/fra"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Tilstande med prioritet"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Udfør"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Indstillinger"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Til"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Tjenesten, der tilbyder denne funktion, får adgang til alle de oplysninger, der er synlige på din skærm, eller som afspilles på din enhed, når du optager eller caster. Dette omfatter oplysninger som f.eks. adgangskoder, betalingsoplysninger, billeder, beskeder og afspillet lyd."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Del eller optag en app"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Vil du dele din skærm med <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Del én app"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Del hele skærmen"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Del én app"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Del hele skærmen"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Når du deler hele skærmen, er alt på din skærm synligt for <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Vær derfor forsigtig med f.eks. adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Når du deler en app, er alt, der vises eller afspilles i den pågældende app, synligt for <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Vær derfor forsigtig med f.eks. adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Del skærm"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellit – god forbindelse"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellit – forbindelsen er tilgængelig"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS-meldinger via satellit"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Nødopkald eller SOS-meldinger via satellit"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Arbejdsprofil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Sjovt for nogle, men ikke for alle"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner giver dig flere muligheder for at justere og tilpasse Android-brugerfladen. Disse eksperimentelle funktioner kan ændres, gå i stykker eller forsvinde i fremtidige udgivelser. Vær forsigtig, hvis du fortsætter."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikon for Skjul"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikon for Udvid"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"eller"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Bevægelse for at gå tilbage"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Bevægelse for at gå til startskærm"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Handlingstast"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 7bfdf67..11dd46e 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> und andere geöffnete Apps haben diesen Screenshot erkannt."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Zu Notiz hinzufügen"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Link einschließen"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Bildschirmaufzeichnung"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Bildschirmaufzeichnung…"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Fortlaufende Benachrichtigung für eine Bildschirmaufzeichnung"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Bildschirmschoner"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Bitte nicht stören"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioritätsmodi"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Keine gekoppelten Geräte verfügbar"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Zum Verbinden oder Trennen eines Geräts tippen"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth verwenden"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Verbunden"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audiofreigabe"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Zum Wechseln oder Teilen des Audiostreams tippen"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gespeichert"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"Verknüpfung aufheben"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivieren"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Einstellungen öffnen"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Sonstiges Gerät"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Übersicht ein-/ausblenden"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritätsmodi"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Fertig"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Einstellungen"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"An"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Der Anbieter dieser App erhält Zugriff auf alle Informationen, die auf deinem Bildschirm sichtbar sind oder von deinem Gerät wiedergegeben werden, während du aufnimmst oder streamst. Dazu gehören beispielsweise Passwörter, Zahlungsdetails, Fotos, Nachrichten und Audioinhalte."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"App teilen oder aufnehmen"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Bildschirm mit <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> teilen?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Eine App streamen"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Gesamten Bildschirm teilen"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Eine App teilen"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Gesamten Bildschirm teilen"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Wenn du den gesamten Bildschirm teilst, ist für <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> alles auf dem Bildschirm sichtbar. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Wenn du eine App streamst, ist für <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> alles sichtbar, was in dieser App angezeigt oder abgespielt wird. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Bildschirm teilen"</string>
@@ -629,7 +637,7 @@
<string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Einstellungen"</string>
<string name="volume_panel_captioning_title" msgid="5984936949147684357">"Automatische Untertitel"</string>
<string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Auf verträglichere Lautstärke eingestellt"</string>
- <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Die Kopfhörerlautstärke war länger als empfohlen hoch eingestellt"</string>
+ <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Die Kopfhörer sind schon länger als empfohlen auf hohe Lautstärke eingestellt"</string>
<string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Die Kopfhörerlautstärke hat für diese Woche das Sicherheitslimit überschritten"</string>
<string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Weiterhören"</string>
<string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Leiser stellen"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellit, Verbindung gut"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellit, Verbindung verfügbar"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Notruf über Satellit"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Notrufe oder SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Arbeitsprofil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Für einige ein Vergnügen, aber nicht für alle"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Mit System UI Tuner erhältst du zusätzliche Möglichkeiten, die Android-Benutzeroberfläche anzupassen. Achtung: Diese Testfunktionen können sich ändern, abstürzen oder in zukünftigen Versionen verschwinden."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Symbol „Minimieren“"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Symbol „Maximieren“"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"oder"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Touch-Geste „Zurück“"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Touch-Geste „Startbildschirm“"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Aktionstaste"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index ed17959..433137c 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Η εφαρμογή <xliff:g id="APPNAME">%1$s</xliff:g> και άλλες ανοικτές εφαρμογές εντόπισαν το στιγμιότυπο οθόνης."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Προσθήκη σε σημείωση"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Συμπερίληψη συνδέσμου"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Εγγραφή οθόνης"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Επεξεργασία εγγραφής οθόνης"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ειδοποίηση σε εξέλιξη για μια περίοδο λειτουργίας εγγραφής οθόνης"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Προφύλαξη οθόνης"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Μην ενοχλείτε"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Λειτουργίες προτεραιότητας"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Δεν υπάρχουν διαθέσιμες συσκευές σε σύζευξη"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Πατήστε για σύνδεση ή αποσύνδεση μιας συσκευής"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Χρήση Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Συνδέθηκε"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Κοινή χρήση ήχου"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Πατήστε για εναλλαγή ή κοινή χρήση ήχου"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Αποθηκεύτηκε"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"αποσύνδεση"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ενεργοποίηση"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Άνοιγμα Ρυθμίσεων"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Άλλη συσκευή"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Εναλλαγή επισκόπησης"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Λειτουργίες προτεραιότητας"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Τέλος"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ρυθμίσεις"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Ενεργό"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Η υπηρεσία που παρέχει αυτήν τη λειτουργία θα έχει πρόσβαση σε όλες τις πληροφορίες που εμφανίζονται στην οθόνη σας ή που αναπαράγονται από τη συσκευή σας κατά την εγγραφή ή τη μετάδοση. Αυτό περιλαμβάνει πληροφορίες όπως κωδικούς πρόσβασης, στοιχεία πληρωμής, φωτογραφίες, μηνύματα και ήχο που αναπαράγετε."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Κοινή χρήση ή εγγραφή εφαρμογής"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Κοινή χρήση της οθόνης με την εφαρμογή <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>;"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Κοινή χρήση μίας εφαρμογής"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Κοινή χρήση ολόκληρης της οθόνης"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Κοινή χρήση μίας εφαρμογής"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Κοινή χρήση ολόκληρης της οθόνης"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Όταν μοιράζεστε ολόκληρη την οθόνη, οτιδήποτε εμφανίζεται στην οθόνη σας είναι ορατό στην εφαρμογή <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Όταν μοιράζεστε μια εφαρμογή, οτιδήποτε εμφανίζεται ή αναπαράγεται σε αυτή την εφαρμογή, είναι ορατό στην εφαρμογή <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Κοινή χρήση οθόνης"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Δορυφορική, καλή σύνδεση"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Δορυφορική, διαθέσιμη σύνδεση"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Δορυφορικό SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Κλήσεις έκτακτης ανάγκης ή SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Προφίλ εργασίας"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Διασκέδαση για ορισμένους, αλλά όχι για όλους"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Το System UI Tuner σάς προσφέρει επιπλέον τρόπους για να τροποποιήσετε και να προσαρμόσετε τη διεπαφή χρήστη Android. Αυτές οι πειραματικές λειτουργίες ενδέχεται να τροποποιηθούν, να παρουσιάσουν σφάλματα ή να καταργηθούν σε μελλοντικές εκδόσεις. Συνεχίστε με προσοχή."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Εικονίδιο σύμπτυξης"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Εικονίδιο ανάπτυξης"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ή"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Κίνηση επιστροφής"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Κίνηση μετάβασης στην αρχική οθόνη"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Πλήκτρο ενέργειας"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 0565be8..cb9dfe5 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> and other open apps detected this screenshot."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Add to note"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Include link"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Screen recorder"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Screen saver"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Do Not Disturb"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Priority modes"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"No paired devices available"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tap to connect or disconnect a device"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Use Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connected"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio sharing"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tap to switch or share audio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Open settings"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Priority modes"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Done"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"On"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages and audio that you play."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Share or record an app"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Share your screen with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Share one app"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Share entire screen"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Share one app"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Share entire screen"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"When you\'re sharing your entire screen, anything on your screen is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"When you\'re sharing an app, anything shown or played in that app is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Share screen"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Emergency calls or SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Collapse icon"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Expand icon"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"or"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Back gesture"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Action key"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 17642f7..3d4c31f 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> and other open apps detected this screenshot."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Add to note"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Include link"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Screen Recorder"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -291,7 +292,7 @@
<string name="start_dreams" msgid="9131802557946276718">"Screen saver"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Do Not Disturb"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Priority modes"</string>
+ <string name="quick_settings_modes_label" msgid="879156359479504244">"Modes"</string>
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"No paired devices available"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tap to connect or disconnect a device"</string>
@@ -300,6 +301,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Use Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connected"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio Sharing"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tap to switch or share audio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string>
@@ -431,7 +433,7 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Open Settings"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Priority modes"</string>
+ <string name="zen_modes_dialog_title" msgid="8854640808100096934">"Modes"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Done"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"On"</string>
@@ -532,8 +534,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Share or record an app"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Share your screen with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Share one app"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Share entire screen"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Share one app"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Share entire screen"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"When you’re sharing your entire screen, anything on your screen is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"When you’re sharing an app, anything shown or played in that app is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Share screen"</string>
@@ -1385,6 +1391,12 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Collapse icon"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Expand icon"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"or"</string>
+ <string name="launch_keyboard_tutorial_notification_title" msgid="8849933155160522519">"Navigate using your keyboard"</string>
+ <string name="launch_keyboard_tutorial_notification_content" msgid="2880339951512757918">"Learn keyboards shortcuts"</string>
+ <string name="launch_touchpad_tutorial_notification_title" msgid="2243780062772196901">"Navigate using your touchpad"</string>
+ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Learn touchpad gestures"</string>
+ <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navigate using your keyboard and touchpad"</string>
+ <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Learn touchpad gestures, keyboards shortcuts, and more"</string>
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Back gesture"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Action key"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 0565be8..cb9dfe5 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> and other open apps detected this screenshot."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Add to note"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Include link"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Screen recorder"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Screen saver"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Do Not Disturb"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Priority modes"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"No paired devices available"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tap to connect or disconnect a device"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Use Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connected"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio sharing"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tap to switch or share audio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Open settings"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Priority modes"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Done"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"On"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages and audio that you play."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Share or record an app"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Share your screen with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Share one app"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Share entire screen"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Share one app"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Share entire screen"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"When you\'re sharing your entire screen, anything on your screen is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"When you\'re sharing an app, anything shown or played in that app is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Share screen"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Emergency calls or SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Collapse icon"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Expand icon"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"or"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Back gesture"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Action key"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 0565be8..cb9dfe5 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> and other open apps detected this screenshot."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Add to note"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Include link"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Screen recorder"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Screen saver"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Do Not Disturb"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Priority modes"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"No paired devices available"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tap to connect or disconnect a device"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Use Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connected"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio sharing"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tap to switch or share audio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Open settings"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Priority modes"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Done"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"On"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages and audio that you play."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Share or record an app"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Share your screen with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Share one app"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Share entire screen"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Share one app"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Share entire screen"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"When you\'re sharing your entire screen, anything on your screen is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"When you\'re sharing an app, anything shown or played in that app is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, audio and video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Share screen"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Emergency calls or SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Collapse icon"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Expand icon"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"or"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Back gesture"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Action key"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index d31d328..eb94d59 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> and other open apps detected this screenshot."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Add to note"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Include link"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Screen Recorder"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processing screen recording"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string>
@@ -291,7 +292,7 @@
<string name="start_dreams" msgid="9131802557946276718">"Screen saver"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Do Not Disturb"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Priority modes"</string>
+ <string name="quick_settings_modes_label" msgid="879156359479504244">"Modes"</string>
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"No paired devices available"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tap to connect or disconnect a device"</string>
@@ -300,6 +301,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Use Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connected"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio Sharing"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tap to switch or share audio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string>
@@ -431,7 +433,7 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Open Settings"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Other device"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Toggle Overview"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Priority modes"</string>
+ <string name="zen_modes_dialog_title" msgid="8854640808100096934">"Modes"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Done"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Settings"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"On"</string>
@@ -532,8 +534,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Share or record an app"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Share your screen with <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Share one app"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Share entire screen"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Share one app"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Share entire screen"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"When you’re sharing your entire screen, anything on your screen is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"When you’re sharing an app, anything shown or played in that app is visible to <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. So be careful with things like passwords, payment details, messages, photos, and audio and video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Share screen"</string>
@@ -1385,6 +1391,12 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Collapse icon"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Expand icon"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"or"</string>
+ <string name="launch_keyboard_tutorial_notification_title" msgid="8849933155160522519">"Navigate using your keyboard"</string>
+ <string name="launch_keyboard_tutorial_notification_content" msgid="2880339951512757918">"Learn keyboards shortcuts"</string>
+ <string name="launch_touchpad_tutorial_notification_title" msgid="2243780062772196901">"Navigate using your touchpad"</string>
+ <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"Learn touchpad gestures"</string>
+ <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"Navigate using your keyboard and touchpad"</string>
+ <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"Learn touchpad gestures, keyboards shortcuts, and more"</string>
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Back gesture"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Home gesture"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Action key"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 53c38e2..2af8bd1 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -104,13 +104,14 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> y otras apps en ejecución detectaron que tomaste una captura de pantalla."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Agregar a la nota"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Incluir vínculo"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Grabadora de pantalla"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando grabación pantalla"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación constante para una sesión de grabación de pantalla"</string>
<string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"¿Quieres grabar la pantalla?"</string>
<string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Grabar una app"</string>
<string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="2794896384693120020">"Grabar toda la pantalla"</string>
- <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Cuando grabes toda la pantalla, se registrará todo lo que se muestre en ella. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string>
+ <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Cuando grabes toda la pantalla, se grabará todo lo que se muestre en ella. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string>
<string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Cuando grabes una app, se registrará todo lo que se muestre o reproduzca en ella. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string>
<string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Grabar pantalla"</string>
<string name="screenrecord_app_selector_title" msgid="3854492366333954736">"Elige una app para grabar"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Protector pantalla"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"No interrumpir"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modos prioritarios"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"No hay dispositivos sincronizados disponibles"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Presiona para conectar o desconectar un dispositivo"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectado"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Uso compartido de audio"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Presiona para cambiar o compartir el audio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Guardado"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activar"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Abrir Configuración"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Otro dispositivo"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Ocultar o mostrar Recientes"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos prioritarios"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Listo"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configuración"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Activado"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"El servicio que brinda esta función tendrá acceso a toda la información que sea visible en la pantalla o que reproduzcas en el dispositivo durante una grabación o transmisión. Se incluyen contraseñas, detalles de pagos, fotos, mensajes y audio que reproduzcas."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Comparte o graba una app"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"¿Quieres compartir pantalla con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Compartir una app"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Compartir pantalla completa"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Compartir una app"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Compartir pantalla completa"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Cuando compartes la pantalla completa, todo lo que se muestre es visible en <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Cuando compartes una app, todo lo que se muestre o reproduzca en ella será visible en <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Compartir pantalla"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, buena conexión"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexión disponible"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS por satélite"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Llamadas de emergencia o SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabajo"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversión solo para algunas personas"</string>
<string name="tuner_warning" msgid="1861736288458481650">"El sintonizador de IU del sistema te brinda más formas para editar y personalizar la interfaz de usuario de Android. Estas funciones experimentales pueden cambiar, dejar de funcionar o no incluirse en futuras versiones. Procede con precaución."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ícono de contraer"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ícono de expandir"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"o"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto atrás"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto para ir a la pantalla principal"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de acción"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 0bebccf..2e823ed 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> y otras aplicaciones abiertas han detectado esta captura de pantalla."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Añadir a nota"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Incluir enlace"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Grabación de pantalla"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando grabación de pantalla"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación continua de una sesión de grabación de la pantalla"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Salvapantallas"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"No molestar"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modos prioritarios"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"No hay dispositivos vinculados disponibles"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Toca para conectar o desconectar un dispositivo"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectado"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Compartir audio"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Toca para cambiar o compartir el audio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Guardado"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activar"</string>
@@ -390,7 +393,7 @@
<string name="performance" msgid="6552785217174378320">"Rendimiento"</string>
<string name="user_interface" msgid="3712869377953950887">"Interfaz de usuario"</string>
<string name="thermal" msgid="6758074791325414831">"Temperatura"</string>
- <string name="custom" msgid="3337456985275158299">"Otro"</string>
+ <string name="custom" msgid="3337456985275158299">"Config. personalizada"</string>
<string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Ajustes de traza personalizados"</string>
<string name="restore_default" msgid="5259420807486239755">"Restaurar ajustes predeterminados"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo Una mano"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Abrir Ajustes"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Otro dispositivo"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Mostrar u ocultar aplicaciones recientes"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos prioritarios"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Hecho"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ajustes"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Activado"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"El servicio que ofrece esta función tendrá acceso a toda la información que se muestre en la pantalla o se reproduzca en el dispositivo mientras grabas o envías contenido, incluidos contraseñas, detalles de pagos, fotos, mensajes y audio que reproduzcas."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Compartir o grabar una aplicación"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"¿Compartir tu pantalla con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Compartir una aplicación"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Compartir toda la pantalla"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Compartir una aplicación"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Compartir toda la pantalla"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Cuando compartes toda tu pantalla, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> puede ver todo lo que hay en ella. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Cuando compartes una aplicación, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> puede ver todo lo que se muestra o reproduce en ella. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Compartir pantalla"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, buena conexión"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexión disponible"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS por satélite"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Llamadas de emergencia o SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabajo"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversión solo para algunos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"El configurador de UI del sistema te ofrece otras formas de modificar y personalizar la interfaz de usuario de Android. Estas funciones experimentales pueden cambiar, fallar o desaparecer en futuras versiones. Te recomendamos que tengas cuidado."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icono de contraer"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icono de desplegar"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"o"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto para volver"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto para ir al inicio"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de acción"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index b2ffa80..09f461f 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ja muud avatud rakendused tuvastasid selle ekraanipildi."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Lisa märkmesse"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Kaasa link"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Ekraanisalvesti"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekraanisalvestuse töötlemine"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Pooleli märguanne ekraanikuva salvestamise seansi puhul"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Ekraanisäästja"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Mitte segada"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioriteetsed režiimid"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Ühtegi seotud seadet pole saadaval"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Puudutage seadme ühendamiseks või ühenduse katkestamiseks"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Kasuta Bluetoothi"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ühendatud"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Heli jagamine"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Puudutage helile lülitumiseks või selle jagamiseks"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvestatud"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"katkesta ühendus"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiveeri"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Ava menüü Seaded"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Muu seade"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Lehe Ülevaade sisse- ja väljalülitamine"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriteetsed režiimid"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Valmis"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Seaded"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Sees"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Seda funktsiooni pakkuv teenus saab juurdepääsu kogu teabele, mis on teie ekraanikuval nähtav või mida seadmes salvestamise või ülekande ajal esitatakse. See hõlmab teavet, nagu paroolid, maksete üksikasjad, fotod, sõnumid ja esitatav heli."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Rakenduse jagamine või salvestamine"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Kas jagada teie ekraani rakendusega <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Jaga üht rakendust"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Jaga kogu ekraani"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Jaga ühte rakendust"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Jaga kogu ekraani"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kogu ekraanikuva jagamisel on kogu sellel kuvatav sisu nähtav rakendusele <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Seega olge ettevaatlik selliste andmetega nagu paroolid, makseteave, sõnumid, fotod ning heli ja video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Rakenduse jagamisel on kogu rakenduses kuvatav või esitatav sisu nähtav rakendusele <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Seega olge ettevaatlik selliste andmetega nagu paroolid, makseteave, sõnumid, fotod ning heli ja video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Jaga ekraani"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliit, hea ühendus"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliit, ühendus on saadaval"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelliit-SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Hädaabikõned või SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Tööprofiil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Kõik ei pruugi sellest rõõmu tunda"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Süsteemi kasutajaliidese tuuner pakub täiendavaid võimalusi Androidi kasutajaliidese muutmiseks ja kohandamiseks. Need katselised funktsioonid võivad muutuda, rikki minna või tulevastest versioonidest kaduda. Olge jätkamisel ettevaatlik."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ahendamisikoon"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Laiendamisikoon"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"või"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Tagasiliikumisliigutus"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Avakuvale liikumise liigutus"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Toiminguklahv"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index d8cff19..329b6e2 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> aplikazioak eta irekitako beste aplikazio batzuek pantaila-argazkia hauteman dute."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Gehitu oharrean"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Sartu esteka"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Pantaila-grabagailua"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Pantaila-grabaketa prozesatzen"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Pantailaren grabaketa-saioaren jakinarazpen jarraitua"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Pantaila-babeslea"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ez molestatzeko modua"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Lehentasunezko moduak"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetootha"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Ez dago parekatutako gailurik erabilgarri"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Sakatu hau gailu bat konektatu edo deskonektatzeko"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Erabili Bluetootha"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Konektatuta"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audioa partekatzea"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Audioa aldatu edo partekatzeko, sakatu hau"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gordeta"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"deskonektatu"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktibatu"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Ireki Ezarpenak"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Beste gailu bat"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aldatu ikuspegi orokorra"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Lehentasunezko moduak"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Eginda"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ezarpenak"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Aktibatuta"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Zerbait grabatzen edo igortzen duzunean, pantailan ikusgai dagoen edo gailuak erreproduzitzen duen informazio guztia erabili ahalko du funtzio hori eskaintzen duen zerbitzuak. Pasahitzak, ordainketen xehetasunak, argazkiak, mezuak eta erreproduzitzen dituzun audioak sartzen dira informazio horretan."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Partekatu edo grabatu aplikazio bat"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioarekin pantaila partekatu nahi duzu?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Partekatu aplikazio bat"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Partekatu pantaila osoa"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Aplikazio bat partekatu"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Pantaila osoa partekatu"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Pantaila osoa partekatzen ari zarenean, pantailan duzun guztia ikus dezake <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Aplikazio bat partekatzen ari zarenean, aplikazio horretan agertzen den edo bertan erreproduzitzen ari den guztia ikusi dezake <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> aplikazioak. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Partekatu pantaila"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelitea, konexio ona"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelitea, konexioa erabilgarri"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelite bidezko SOS komunikazioa"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Larrialdi-deiak edo SOS komunikazioa"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Laneko profila"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Dibertsioa batzuentzat, baina ez guztientzat"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sistemaren erabiltzaile-interfazearen konfiguratzaileak Android erabiltzaile-interfazea moldatzeko eta pertsonalizatzeko modu gehiago eskaintzen dizkizu. Baliteke eginbide esperimental horiek hurrengo kaleratzeetan aldatuta, etenda edo desagertuta egotea. Kontuz erabili."</string>
@@ -1195,7 +1202,7 @@
<string name="select_conversation_text" msgid="3376048251434956013">"Sakatu elkarrizketa bat orri nagusian gehitzeko"</string>
<string name="no_conversations_text" msgid="5354115541282395015">"Azkenaldiko elkarrizketak agertuko dira hemen"</string>
<string name="priority_conversations" msgid="3967482288896653039">"Lehentasunezko elkarrizketak"</string>
- <string name="recent_conversations" msgid="8531874684782574622">"Azken elkarrizketak"</string>
+ <string name="recent_conversations" msgid="8531874684782574622">"Azkenaldiko elkarrizketak"</string>
<string name="days_timestamp" msgid="5821854736213214331">"Duela <xliff:g id="DURATION">%1$s</xliff:g> egun"</string>
<string name="one_week_timestamp" msgid="4925600765473875590">"Duela astebete"</string>
<string name="two_weeks_timestamp" msgid="9111801081871962155">"Duela bi aste"</string>
@@ -1219,7 +1226,7 @@
<string name="status_before_loading" msgid="1500477307859631381">"Laster agertuko da edukia"</string>
<string name="missed_call" msgid="4228016077700161689">"Dei galdua"</string>
<string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string>
- <string name="people_tile_description" msgid="8154966188085545556">"Ikusi azken mezuak, dei galduak eta egoerei buruzko informazio eguneratua"</string>
+ <string name="people_tile_description" msgid="8154966188085545556">"Ikusi azkenaldiko mezuak, dei galduak eta egoerei buruzko informazio eguneratua"</string>
<string name="people_tile_title" msgid="6589377493334871272">"Elkarrizketa"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"Ez molestatzeko moduak pausatu du"</string>
<string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> erabiltzaileak mezu bat bidali du: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Tolesteko ikonoa"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Zabaltzeko ikonoa"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"edo"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Atzera egiteko keinua"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Orri nagusira joateko keinua"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Ekintza-tekla"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 5b17c44..f845027 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> و سایر برنامههای باز این نماگرفت را تشخیص دادند."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"افزودن به یادداشت"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"اضافه کردن پیوند"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"ضبطکن صفحهنمایش"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"درحال پردازش ضبط صفحهنمایش"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"اعلان درحال انجام برای جلسه ضبط صفحهنمایش"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"محافظ صفحه"</string>
<string name="ethernet_label" msgid="2203544727007463351">"اترنت"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"مزاحم نشوید"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"حالتهای اولویتدار"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"بلوتوث"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"هیچ دستگاه مرتبط شدهای موجود نیست"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"برای اتصال یا قطع اتصال دستگاه، تکضرب بزنید"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"استفاده از بلوتوث"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"متصل"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"اشتراک صدا"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"برای فعال کردن و همرسانی صدا، تکضرب بزنید"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ذخیرهشده"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"قطع اتصال"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"فعال کردن"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"باز کردن تنظیمات"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"دستگاه دیگر"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"تغییر وضعیت نمای کلی"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"حالتهای اولویتدار"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"تمام"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"تنظیمات"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"روشن"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"سرویس ارائهدهنده این عملکرد به همه اطلاعاتی که روی صفحهنمایش قابلمشاهد است و هنگام ضبط کردن یا پخش محتوا از دستگاهتان پخش میشود دسترسی خواهد داشت. این شامل اطلاعاتی مانند گذرواژهها، جزئیات پرداخت، عکسها، پیامها، و صداهایی که پخش میکنید میشود."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"همرسانی یا ضبط برنامه"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"صفحهنمایش با <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> همرسانی شود؟"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"همرسانی یک برنامه"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"همرسانی کل صفحهنمایش"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"همرسانی کردن یک برنامه"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"همرسانی کردن کل صفحهنمایش"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"وقتی کل صفحهنمایش را همرسانی میکنید، هر چیزی که روی صفحهنمایش شما وجود داشته باشد برای <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> قابلمشاهده خواهد بود. درنتیجه مراقب چیزهایی مثل گذرواژهها، جزئیات پرداخت، پیامها، عکسها، و صدا و تصویر باشید."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"وقتی برنامهای را همرسانی میکنید، هر چیزی که در آن برنامه نمایش داده شود یا پخش شود برای <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> قابلمشاهده خواهد بود. درنتیجه مراقب چیزهایی مثل گذرواژهها، جزئیات پرداخت، پیامها، عکسها، و صدا و تصویر باشید."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"همرسانی صفحهنمایش"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ماهواره، اتصال خوب است"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ماهواره، اتصال دردسترس است"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"درخواست کمک ماهوارهای"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"تماس اضطراری یا درخواست کمک اضطراری"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"نمایه کاری"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"برای بعضی افراد سرگرمکننده است اما نه برای همه"</string>
<string name="tuner_warning" msgid="1861736288458481650">"«تنظیمکننده واسط کاربری سیستم» روشهای بیشتری برای تنظیم دقیق و سفارشی کردن واسط کاربری Android در اختیار شما قرار میدهد. ممکن است این ویژگیهای آزمایشی تغییر کنند، خراب شوند یا در نسخههای آینده جود نداشته باشند. با احتیاط ادامه دهید."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"نماد جمع کردن"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"نماد ازهم بازکردن"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"یا"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"اشاره برگشت"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"اشاره صفحه اصلی"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"دکمه کنش"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 9244bec..b9afcd5 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ja jotkin muut sovellukset havaitsivat tämän kuvakaappauksen."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Lisää muistiinpanoon"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Lisää linkki"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Näytön tallentaja"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Näytön tallennusta käsitellään"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Pysyvä ilmoitus näytön tallentamisesta"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Näytönsäästäjä"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Älä häiritse"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioriteettitilat"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Laitepareja ei ole käytettävissä"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Muodosta yhteys laitteeseen tai katkaise yhteys napauttamalla"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Käytä Bluetoothia"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Yhdistetty"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audionjako"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Vaihda tai jaa audiota napauttamalla"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Tallennettu"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"katkaise yhteys"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivoi"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Avaa Asetukset"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Muu laite"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Näytä/piilota viimeisimmät"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriteettitilat"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Valmis"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Asetukset"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Päällä"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Ominaisuuden tarjoavalla palvelulla on pääsy kaikkiin näytölläsi näkyviin tietoihin ja tietoihin laitteesi toistamasta sisällöstä tallennuksen tai striimauksen aikana. Näitä tietoja ovat esimerkiksi salasanat, maksutiedot, kuvat, viestit ja toistettava audiosisältö."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Jaa sovellus tai tallenna sen sisältöä"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Saako <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> nähdä näyttösi?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Jaa yksi sovellus"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Jaa koko näyttö"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Jaa yksi sovellus"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Jaa koko näyttö"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kun jaat koko näytön, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> näkee kaiken sen sisälllön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kun jaat sovelluksen, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> näkee kaiken sovelluksessa näkyvän tai toistetun sisällön. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Jaa näyttö"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliitti, hyvä yhteys"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliitti, yhteys saatavilla"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Hätäpuhelut tai Satellite SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Työprofiili"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Ei sovellu kaikkien käyttöön"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner antaa lisämahdollisuuksia Android-käyttöliittymän muokkaamiseen. Nämä kokeelliset ominaisuudet voivat muuttua, lakata toimimasta tai kadota milloin tahansa. Jatka omalla vastuullasi."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Tiivistyskuvake"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Laajennuskuvake"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"tai"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Takaisin-ele"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Etusivu-ele"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Toimintonäppäin"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 41305af..07e131e 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> et d\'autres applis ouvertes ont détecté cette capture d\'écran."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Ajouter à une note"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Inclure le lien"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Enregistreur d\'écran"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Trait. de l\'enregist. d\'écran…"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement d\'écran"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Écran de veille"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ne pas déranger"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modes prioritaires"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Aucun des appareils associés n\'est disponible"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Touchez pour connecter ou déconnecter un appareil"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Utiliser le Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connecté"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Partage audio"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Touchez pour passer d\'un appareil à l\'autre ou pour partager le contenu audio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Enregistré"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"Déconnecter"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"Activer"</string>
@@ -307,7 +310,7 @@
<string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Les fonctionnalités comme Partage rapide et Localiser mon appareil utilisent le Bluetooth"</string>
<string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Le Bluetooth s\'activera demain matin"</string>
<string name="quick_settings_bluetooth_audio_sharing_button" msgid="7545274861795853838">"Partager l\'audio"</string>
- <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="3069309588231072128">"Partage de l\'audio en cours…"</string>
+ <string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="3069309588231072128">"Partage de l\'audio en cours"</string>
<string name="quick_settings_bluetooth_audio_sharing_button_accessibility" msgid="7604615019302091708">"entrer les paramètres de partage audio"</string>
<string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
<string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"Audio"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Ouvrir les paramètres"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Autre appareil"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Basculer l\'aperçu"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modes prioritaires"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"OK"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Paramètres"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Activé"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Le service offrant cette fonction aura accès à toute l\'information qui est visible sur votre écran ou lu sur votre appareil pendant que vous enregistrez ou diffusez. Cela comprend des renseignements comme les mots de passe, les détails du paiement, les photos, les messages et le contenu audio que vous faites jouer."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Partager ou enregistrer une appli"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Partager votre écran avec <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Partager une appli"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Partager l\'intégralité de l\'écran"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Partager une appli"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Partager l\'intégralité de l\'écran"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Lorsque vous partagez l\'intégralité de votre écran, tout ce qui s\'y trouve est visible par <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Par conséquent, soyez prudent avec les mots de passe, les détails du mode de paiement, les messages, les photos et les contenus audio et vidéo."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Lorsque vous partagez une appli, tout ce qui s\'y affiche ou s\'y joue est visible par <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Par conséquent, soyez prudent avec les mots de passe, les détails du mode de paiement, les messages, les photos et les contenus audio et vidéo."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Partager l\'écran"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Bonne connexion satellite"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Connexion satellite accessible"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS par satellite"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Appels d\'urgence ou SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil professionnel"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Divertissant pour certains, mais pas pour tous"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner vous propose de nouvelles manières d\'adapter et de personnaliser l\'interface utilisateur d\'Android. Ces fonctionnalités expérimentales peuvent être modifiées, cesser de fonctionner ou disparaître dans les versions futures. À utiliser avec prudence."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icône Réduire"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icône Développer"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Geste de retour"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Geste d\'accès à l\'écran d\'accueil"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Touche d\'action"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 4df98cf..9d3bbd7 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -104,13 +104,14 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> et d\'autres applis ouvertes ont détecté cette capture d\'écran."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Ajouter à la note"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Inclure le lien"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Enregistreur d\'écran"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Enregistrement de l\'écran…"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement de l\'écran"</string>
<string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Enregistrer l\'écran ?"</string>
<string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Enregistrer une appli"</string>
<string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="2794896384693120020">"Enregistrer tout l\'écran"</string>
- <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Lorsque vous enregistrez tout votre écran, tout ce qui s\'affiche sur celui-ci est enregistré. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages, photos et contenus audio et vidéo."</string>
+ <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Lorsque vous enregistrez l\'intégralité de votre écran, tout ce qui s\'y affiche est enregistré. Faites donc attention aux éléments tels que les mots de passe, les détails du mode de paiement, les messages, les photos, et les contenus audio et vidéo."</string>
<string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Lorsque vous enregistrez une appli, tout ce qui est affiché ou lu dans celle-ci est enregistré. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages, photos et contenus audio et vidéo."</string>
<string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Enregistrer l\'écran"</string>
<string name="screenrecord_app_selector_title" msgid="3854492366333954736">"Choisir l\'appli à enregistrer"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Économiseur d\'écran"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ne pas déranger"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modes prioritaires"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Aucun appareil associé disponible."</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Appuyez pour connecter ou déconnecter un appareil"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Utiliser le Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connecté"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Partage audio"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Appuyez pour activer ou partager l\'audio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Enregistré"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"dissocier"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activer"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Ouvrir les paramètres"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Autre appareil"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activer/Désactiver l\'écran Récents"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modes prioritaires"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"OK"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Paramètres"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Activé"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Le service qui fournit cette fonction aura accès à toutes les infos visibles sur votre écran ou lues depuis votre appareil pendant un enregistrement ou une diffusion de contenu. Il peut s\'agir de mots de passe, détails de mode de paiement, photos, messages ou encore contenus audio lus."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Partager ou enregistrer une appli"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Partager votre écran avec <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Partager une appli"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Partager tout l\'écran"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Partager une appli"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Partager tout l\'écran"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Lorsque vous partagez tout votre écran, l\'ensemble de son contenu est visible par <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Faites donc attention aux éléments tels que les mots de passe, les détails du mode de paiement, les messages, les photos et les contenus audio et vidéo."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Lorsque vous partagez une appli, tout ce qui est affiché ou lu dans celle-ci est visible par <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Faites donc attention aux éléments tels que les mots de passe, les détails du mode de paiement, les messages, les photos et les contenus audio et vidéo."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Partager l\'écran"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Bonne connexion satellite"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Connexion satellite disponible"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS par satellite"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Appels d\'urgence ou SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil professionnel"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Divertissant pour certains, mais pas pour tous"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner vous propose de nouvelles manières d\'adapter et de personnaliser l\'interface utilisateur Android. Ces fonctionnalités expérimentales peuvent être modifiées, cesser de fonctionner ou disparaître dans les versions futures. À utiliser avec prudence."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icône Réduire"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icône Développer"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Geste Retour"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Geste Accueil"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Touche d\'action"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 1fe1242..6281570 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> e outras aplicacións abertas detectaron esta captura de pantalla."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Engadir a unha nota"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Incluír ligazón"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Gravadora da pantalla"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Procesando gravación pantalla"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación de actividade en curso sobre unha sesión de gravación de pantalla"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Protector pantalla"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Non molestar"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modos de prioridade"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Non hai dispositivos vinculados dispoñibles"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Toca para conectar ou desconectar un dispositivo"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Estableceuse a conexión"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio compartido"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Toca para cambiar ou compartir o audio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gardouse"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activar"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Abrir Configuración"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Outro dispositivo"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Activar/desactivar Visión xeral"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos de prioridade"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Feito"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configuración"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Activado"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"O servizo que proporciona esta función terá acceso a toda a información visible na pantalla ou reproducida desde o teu dispositivo mentres graves ou emitas contido. Isto inclúe datos como contrasinais, detalles de pago, fotos, mensaxes e o audio que reproduzas."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Compartir ou gravar unha aplicación"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Queres compartir a pantalla con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Compartir unha aplicación"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Compartir toda a pantalla"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Compartir unha aplicación"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Compartir toda a pantalla"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Se compartes toda a pantalla, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> poderá ver todo o contido que apareza nela. Ten coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como co contido de audio e de vídeo."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Se compartes toda a pantalla, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> poderá ver todo o contido que apareza ou se reproduza nesa aplicación. Ten coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como co contido de audio e de vídeo."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Compartir pantalla"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, boa conexión"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexión dispoñible"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS por satélite"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Chamadas de emerxencia ou SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de traballo"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversión só para algúns"</string>
<string name="tuner_warning" msgid="1861736288458481650">"O configurador da IU do sistema ofréceche formas adicionais de modificar e personalizar a interface de usuario de Android. Estas funcións experimentais poden cambiar, interromperse ou desaparecer en futuras versións. Continúa con precaución."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icona de contraer"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icona de despregar"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Xesto para volver"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Xesto para ir ao inicio"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de acción"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 7ecc057..2be88f2 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> અને કામ કરતી અન્ય ઍપ દ્વારા આ સ્ક્રીનશૉટ લેવાયાની ભાળ મેળવવામાં આવી."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"નોંધમાં ઉમેરો"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"લિંક શામેલ કરો"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"સ્ક્રીન રેકોર્ડર"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"સ્ક્રીન રેકૉર્ડિંગ ચાલુ છે"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"સ્ક્રીન રેકોર્ડિંગ સત્ર માટે ચાલુ નોટિફિકેશન"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"સ્ક્રીન સેવર"</string>
<string name="ethernet_label" msgid="2203544727007463351">"ઇથરનેટ"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"ખલેલ પાડશો નહીં"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"પ્રાધાન્યતાના મોડ"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"બ્લૂટૂથ"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"કોઈ જોડી કરેલ ઉપકરણો ઉપલબ્ધ નથી"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"કોઈ ડિવાઇસ કનેક્ટ કરવા કે ડિસ્કનેક્ટ કરવા માટે ટૅપ કરો"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"બ્લૂટૂથનો ઉપયોગ કરો"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"કનેક્ટેડ છે"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ઑડિયો શેરિંગ"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ઑડિયો પર સ્વિચ કરવા કે તેને શેર કરવા માટે બે વાર ટૅપ કરો"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"સાચવેલું"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ડિસ્કનેક્ટ કરો"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"સક્રિય કરો"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"સેટિંગ ખોલો"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"અન્ય ડિવાઇસ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ઝલકને ટૉગલ કરો"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"પ્રાધાન્યતાના મોડ"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"થઈ ગયું"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"સેટિંગ"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"ચાલુ"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"રેકોર્ડ અથવા કાસ્ટ કરતી વખતે, આ સુવિધા આપતી સેવાને તમારી સ્ક્રીન પર દેખાતી હોય અથવા તમારા ડિવાઇસ પર ચલાવવામાં આવતી હોય તેવી બધી માહિતીનો ઍક્સેસ હશે. જેમાં પાસવર્ડ, ચુકવણીની વિગતો, ફોટા, મેસેજ અને તમે વગાડો છો તે ઑડિયો જેવી માહિતીનો સમાવેશ થાય છે."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"કોઈ ઍપ શેર કરો અથવા રેકોર્ડ કરો"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> સાથે તમારી સ્ક્રીન શેર કરીએ?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"એક ઍપ શેર કરો"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"સંપૂર્ણ સ્ક્રીન શેર કરો"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"કોઈ ઍપ શેર કરો"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"સંપૂર્ણ સ્ક્રીન શેર કરો"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"જ્યારે તમે તમારી સંપૂર્ણ સ્ક્રીનને શેર કરી રહ્યાં હો, ત્યારે તમારી સ્ક્રીન પરની કોઈપણ વસ્તુ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ને દેખાય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"જ્યારે તમે કોઈ ઍપને શેર કરી રહ્યાં હો, ત્યારે તે ઍપ પર બતાવવામાં કે ચલાવવામાં આવતી હોય તેવી બધી વસ્તુ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ને દેખાય છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"સ્ક્રીન શેર કરો"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"સૅટલાઇટ, સારું કનેક્શન"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"સૅટલાઇટ, કનેક્શન ઉપલબ્ધ છે"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"ઇમર્જન્સી સૅટલાઇટ સહાય"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ઇમર્જન્સી કૉલ અથવા SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ઑફિસની પ્રોફાઇલ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"કેટલાક માટે મજા પરંતુ બધા માટે નહીં"</string>
<string name="tuner_warning" msgid="1861736288458481650">"સિસ્ટમ UI ટ્યૂનર તમને Android વપરાશકર્તા ઇન્ટરફેસને ટ્વીક અને કસ્ટમાઇઝ કરવાની વધારાની રીતો આપે છે. ભાવિ રીલિઝેસમાં આ પ્રાયોગિક સુવિધાઓ બદલાઈ, ભંગ અથવા અદૃશ્ય થઈ શકે છે. સાવધાની સાથે આગળ વધો."</string>
@@ -1222,7 +1229,7 @@
<string name="people_tile_description" msgid="8154966188085545556">"તાજેતરના મેસેજ, ચૂકી ગયેલા કૉલ અને સ્ટેટસ અપડેટ જુઓ"</string>
<string name="people_tile_title" msgid="6589377493334871272">"વાતચીત"</string>
<string name="paused_by_dnd" msgid="7856941866433556428">"\'ખલેલ પાડશો નહીં\'ની સુવિધા દ્વારા થોભાવેલું"</string>
- <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા કોઈ સંદેશ મોકલવામાં આવ્યો: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
+ <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા કોઈ મેસેજ મોકલવામાં આવ્યો: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string>
<string name="new_notification_image_content_description" msgid="6017506886810813123">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા કોઈ છબી મોકલવામાં આવી"</string>
<string name="new_status_content_description" msgid="6046637888641308327">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા નવી સ્ટેટસ અપડેટ પોસ્ટ કરવામાં આવી: <xliff:g id="STATUS">%2$s</xliff:g>"</string>
<string name="person_available" msgid="2318599327472755472">"ઉપલબ્ધ છે"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"\'નાનું કરો\'નું આઇકન"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"\'મોટું કરો\'નું આઇકન"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"અથવા"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"પાછળ જવાનો સંકેત"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"હોમ સ્ક્રીન પર જવાનો સંકેત"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ઍક્શન કી"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index c6a5e57..7c267bf 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -104,13 +104,14 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> और खुले हुए अन्य ऐप्लिकेशन को इस स्क्रीनशॉट का पता चला है."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"नोट में जोड़ें"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"लिंक जोड़ें"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"स्क्रीन रिकॉर्डर"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रीन रिकॉर्डिंग को प्रोसेस किया जा रहा है"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"स्क्रीन रिकॉर्ड सेशन के लिए जारी सूचना"</string>
<string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"क्या आपको स्क्रीन रिकॉर्ड करनी है?"</string>
<string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"एक ऐप्लिकेशन की रिकॉर्डिंग करें"</string>
<string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="2794896384693120020">"पूरी स्क्रीन रिकॉर्ड करें"</string>
- <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"पूरी स्क्रीन रिकॉर्ड करते समय, स्क्रीन पर दिखने वाली हर चीज़ रिकॉर्ड की जाती है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, और डिवाइस पर चल रहे ऑडियो और वीडियो को लेकर सावधानी बरतें."</string>
+ <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"पूरी स्क्रीन रिकॉर्ड करते समय, स्क्रीन पर दिखने वाली हर चीज़ रिकॉर्ड की जाती है. इसलिए पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, डिवाइस पर चल रहे ऑडियो और वीडियो, और फ़ोटो जैसी चीज़ों को लेकर सावधानी बरतें."</string>
<string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"किसी ऐप्लिकेशन को रिकॉर्ड करने के दौरान, उस पर दिख रहा कॉन्टेंट या चल रहा मीडिया दूसरी स्क्रीन पर भी रिकॉर्ड होता है. इसलिए, रिकॉर्ड करते समय पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, ऑडियो, और वीडियो को लेकर सावधानी बरतें."</string>
<string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"स्क्रीन रिकॉर्ड करें"</string>
<string name="screenrecord_app_selector_title" msgid="3854492366333954736">"रिकॉर्ड करने के लिए ऐप्लिकेशन चुनें"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"स्क्रीन सेवर"</string>
<string name="ethernet_label" msgid="2203544727007463351">"ईथरनेट"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"परेशान न करें"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"अहम मोड"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ब्लूटूथ"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"कोई भी युग्मित डिवाइस उपलब्ध नहीं"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"किसी डिवाइस को कनेक्ट या डिसकनेक्ट करने के लिए टैप करें"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ब्लूटूथ इस्तेमाल करें"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"कनेक्ट है"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ऑडियो शेयर करने की सुविधा"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ऑडियो को स्विच या शेयर करने के लिए टैप करें"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"सेव किया गया"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"डिसकनेक्ट करें"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"चालू करें"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"सेटिंग खोलें"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"अन्य डिवाइस"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"खास जानकारी टॉगल करें"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"अहम मोड"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"हो गया"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"सेटिंग"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"चालू है"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"रिकॉर्ड या कास्ट करते समय, इस सुविधा को उपलब्ध कराने वाली सेवा के पास आपकी स्क्रीन पर दिख रही जानकारी या डिवाइस पर चल रहे हर मीडिया का ऐक्सेस होता है. जैसे, पासवर्ड, पेमेंट के तरीके की जानकारी, फ़ोटो, मैसेज, और डिवाइस पर चल रहा ऑडियो."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"ऐप्लिकेशन शेयर करें या उसकी रिकॉर्डिंग करें"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"क्या आपको <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> पर अपनी स्क्रीन शेयर करनी है?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"एक ऐप्लिकेशन शेयर करें"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"पूरी स्क्रीन शेयर करें"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"एक ऐप्लिकेशन शेयर करें"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"पूरी स्क्रीन शेयर करें"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"जब पूरी स्क्रीन शेयर की जाती है, तो आपकी स्क्रीन पर दिख रहा पूरा कॉन्टेंट <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> पर दिखता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, ऑडियो, और वीडियो को लेकर सावधानी बरतें."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"जब कोई ऐप्लिकेशन शेयर किया जाता है, तो उस ऐप्लिकेशन में दिख रहा या चलाया जा रहा पूरा कॉन्टेंट <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> पर दिखता है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, ऑडियो, और वीडियो को लेकर सावधानी बरतें."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"स्क्रीन शेयर करें"</string>
@@ -628,8 +636,8 @@
<string name="sound_settings" msgid="8874581353127418308">"आवाज़ और वाइब्रेशन"</string>
<string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"सेटिंग"</string>
<string name="volume_panel_captioning_title" msgid="5984936949147684357">"लाइव कैप्शन"</string>
- <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"आवाज़ को कम करके, सुरक्षित लेवल पर सेट कर दिया गया है"</string>
- <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"हेडफ़ोन की आवाज़ सुझाए गए समय से देर तक ज़्यादा रही"</string>
+ <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"आवाज़ को कम करके, सुरक्षित लेवल पर सेट किया गया"</string>
+ <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"हेडफ़ोन की आवाज़ सुझाए गए समय के बाद भी ज़्यादा रही"</string>
<string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"इस हफ़्ते के लिए हेडफ़ोन की आवाज़, सुझाई गई सीमा से ज़्यादा हो गई है"</string>
<string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"सुनना जारी रखें"</string>
<string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"आवाज़ कम करें"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"सैटलाइट कनेक्शन अच्छा है"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"सैटलाइट कनेक्शन उपलब्ध है"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"सैटलाइट एसओएस"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"आपातकालीन कॉल या एसओएस"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"वर्क प्रोफ़ाइल"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"कुछ के लिए मज़ेदार लेकिन सबके लिए नहीं"</string>
<string name="tuner_warning" msgid="1861736288458481650">"सिस्टम यूज़र इंटरफ़ेस (यूआई) ट्यूनर, आपको Android यूज़र इंटरफ़ेस में सुधार लाने और उसे अपनी पसंद के हिसाब से बदलने के कुछ और तरीके देता है. प्रयोग के तौर पर इस्तेमाल हो रहीं ये सुविधाएं आगे चल कर रिलीज़ की जा सकती हैं, रोकी जा सकती हैं या दिखाई देना बंद हो सकती हैं. सावधानी से आगे बढ़ें."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"छोटा करने का आइकॉन"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"बड़ा करने का आइकॉन"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"या"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"पीछे जाने का जेस्चर"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"होम स्क्रीन पर जाने का जेस्चर"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ऐक्शन बटन"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 2edf138..bdf6e13 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> i druge otvorene aplikacije otkrile su ovu snimku zaslona."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Dodaj bilješci"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Uključi vezu"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Snimač zaslona"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrada snimanja zaslona"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Tekuća obavijest za sesiju snimanja zaslona"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Čuvar zaslona"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ne uznemiravaj"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioritetni načini"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Upareni uređaji nisu dostupni"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Dodirnite da biste povezali uređaj ili prekinuli vezu s njim"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Koristi Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Povezano"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Zajedničko slušanje"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Dodirnite za prebacivanje ili dijeljenje zvuka"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Spremljeno"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekini vezu"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiviraj"</string>
@@ -389,7 +392,7 @@
<string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Snimanje zaslona"</string>
<string name="performance" msgid="6552785217174378320">"Izvedba"</string>
<string name="user_interface" msgid="3712869377953950887">"Korisničko sučelje"</string>
- <string name="thermal" msgid="6758074791325414831">"Termalno"</string>
+ <string name="thermal" msgid="6758074791325414831">"Pregrijavanje"</string>
<string name="custom" msgid="3337456985275158299">"Prilagođeno"</string>
<string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Postavke prilagođenog praćenja"</string>
<string name="restore_default" msgid="5259420807486239755">"Vrati na zadano"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Otvori postavke"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Ostali uređaji"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Uključivanje/isključivanje pregleda"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritetni načini"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gotovo"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Postavke"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Uključeno"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Usluga koja pruža ovu funkciju imat će pristup svim podacima koji su vidljivi na vašem zaslonu ili koji se reproduciraju s vašeg uređaja tijekom snimanja ili emitiranja. To uključuje podatke kao što su zaporke, podaci o plaćanju, fotografije, poruke i audiozapisi koje reproducirate."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Dijeljenje ili snimanje pomoću aplikacije"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Želite li dijeliti zaslon s aplikacijom <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Dijeljenje jedne aplikacije"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Dijeljenje cijelog zaslona"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Dijeljenje jedne aplikacije"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Dijeljenje cijelog zaslona"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kada dijelite cijeli zaslon, sve na zaslonu bit će vidljivo aplikaciji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Stoga pazite na stvari kao što su zaporke, podaci o plaćanju, poruke, fotografije te audio i videozapisi."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kada dijelite aplikaciju, sve što se prikazuje ili reproducira u toj aplikaciji bit će vidljivo aplikaciji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Stoga pazite na stvari kao što su zaporke, podaci o plaćanju, poruke, fotografije te audio i videozapisi."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Dijeljenje zaslona"</string>
@@ -629,7 +637,7 @@
<string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Postavke"</string>
<string name="volume_panel_captioning_title" msgid="5984936949147684357">"Automatski titlovi"</string>
<string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Glasnoća je stišana na sigurniju razinu"</string>
- <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Glasnoća u slušalicama pojačana je dulje nego što se preporučuje"</string>
+ <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Zvuk u slušalicama bio je preglasan dulje nego što se preporučuje"</string>
<string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Glasnoća slušalica premašila je sigurno ograničenje za ovaj tjedan"</string>
<string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Nastavi slušati"</string>
<string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Stišaj"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobra veza"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, veza je dostupna"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS putem satelita"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Hitni pozivi ili SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Poslovni profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Ugađanje korisničkog sučelja sustava pruža vam dodatne načine za prilagodbu korisničkog sučelja Androida. Te se eksperimentalne značajke mogu promijeniti, prekinuti ili nestati u budućim izdanjima. Nastavite uz oprez."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona za sažimanje"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona za proširivanje"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ili"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Pokret za povratak"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Pokret za otvaranje početnog zaslona"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tipka za radnju"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 36bae57..773d9ba 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"A(z) <xliff:g id="APPNAME">%1$s</xliff:g> és más nyitott alkalmazások észlelték ezt a képernyőképet."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Hozzáadás jegyzethez"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Linkkel együtt"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Képernyőrögzítő"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Képernyőrögzítés feldolgozása"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Folyamatban lévő értesítés képernyőrögzítési munkamenethez"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Képernyővédő"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ne zavarjanak"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioritási módok"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Nem áll rendelkezésre párosított eszköz"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Koppintson egy eszköz csatlakoztatásához vagy leválasztásához"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth használata"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Csatlakozva"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Hang megosztása"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Koppintással átkapcsolhatja vagy megoszthatja a hangot"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Mentve"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"leválasztás"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiválás"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Beállítások megnyitása"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Más eszköz"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Áttekintés be- és kikapcsolása"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritási módok"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Kész"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Beállítások"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Be"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"A funkciót biztosító szolgáltatás hozzáfér majd minden olyan információhoz, amely látható az Ön képernyőjén, illetve amelyet az Ön eszközéről játszanak le rögzítés vagy átküldés közben. Ez olyan információkat is tartalmaz, mint a jelszavak, a fizetési részletek, a fotók, az üzenetek és a lejátszott audiotartalmak."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Alkalmazás megosztása vagy rögzítése"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Megosztja a képernyőjét a(z) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> alkalmazással?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Egyetlen alkalmazás megosztása"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"A teljes képernyő megosztása"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Egyetlen alkalmazás megosztása"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"A teljes képernyő megosztása"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"A teljes képernyő megosztása esetén a képernyő teljes tartalma látható lesz a(z) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> számára. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Alkalmazás megosztása közben az adott appban megjelenített vagy lejátszott minden tartalom látható a(z) <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> számára. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Képernyő megosztása"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Műhold, jó kapcsolat"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Műhold, van rendelkezésre álló kapcsolat"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Műholdas SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Segélyhívás vagy SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Munkaprofil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Egyeseknek tetszik, másoknak nem"</string>
<string name="tuner_warning" msgid="1861736288458481650">"A Kezelőfelület-hangoló az Android felhasználói felületének szerkesztéséhez és testreszabásához nyújt további megoldásokat. Ezek a kísérleti funkciók változhatnak vagy megsérülhetnek a későbbi kiadásokban, illetve eltűnhetnek azokból. Körültekintően járjon el."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Összecsukás ikon"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Kibontás ikon"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"vagy"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Vissza kézmozdulat"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Kezdőképernyő kézmozdulat"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Műveletbillentyű"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 24e9065..6a64c5d 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g>-ն ու բացված այլ հավելվածներ հայտնաբերել են այս սքրինշոթը։"</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Ավելացնել նշմանը"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Ներառել հղումը"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Էկրանի տեսագրում"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Էկրանի տեսագրության մշակում"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Էկրանի տեսագրման աշխատաշրջանի ընթացիկ ծանուցում"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Էկրանապահ"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Չանհանգստացնել"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Կարևոր ռեժիմներ"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Զուգակցված սարքեր չկան"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Հպեք՝ սարք միացնելու կամ անջատելու համար"</string>
@@ -300,13 +302,14 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Միացնել Bluetooth-ը"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Միացված է"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Աուդիոյի փոխանցում"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Հպեք՝ աուդիոն փոխանջատելու կամ դրանով կիսվելու համար"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Պահված է"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"անջատել"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ակտիվացնել"</string>
<string name="turn_on_bluetooth_auto_tomorrow" msgid="3345758139235739006">"Ավտոմատ միացնել վաղը"</string>
<string name="turn_on_bluetooth_auto_info_disabled" msgid="682984290339848844">"Bluetooth-ն օգտագործում են, օրինակ, Quick Share և «Գտնել իմ սարքը» գործառույթները"</string>
<string name="turn_on_bluetooth_auto_info_enabled" msgid="7440944034584560279">"Bluetooth-ը կմիանա վաղն առավոտյան"</string>
- <string name="quick_settings_bluetooth_audio_sharing_button" msgid="7545274861795853838">"Փոխանցել աուդիո"</string>
+ <string name="quick_settings_bluetooth_audio_sharing_button" msgid="7545274861795853838">"Փոխանցել աուդիոն"</string>
<string name="quick_settings_bluetooth_audio_sharing_button_sharing" msgid="3069309588231072128">"Աուդիոյի փոխանցում"</string>
<string name="quick_settings_bluetooth_audio_sharing_button_accessibility" msgid="7604615019302091708">"անցնել աուդիոյի փոխանցման կարգավորումներ"</string>
<string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Բացել կարգավորումները"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Այլ սարք"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Միացնել/անջատել համատեսքը"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Կարևոր ռեժիմներ"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Պատրաստ է"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Կարգավորումներ"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Միացված է"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Տեսագրման և հեռարձակման ընթացքում ծառայությունների մատակարարին հասանելի կլինեն ձեր սարքի էկրանին ցուցադրվող տեղեկությունները և ձեր սարքով նվագարկվող նյութերը։ Սա ներառում է այնպիսի տեղեկություններ, ինչպիսիք են, օրինակ, գաղտնաբառերը, վճարային տվյալները, լուսանկարները, հաղորդագրությունները և նվագարկվող աուդիո ֆայլերը։"</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Հավելվածի էկրանի ցուցադրում կամ տեսագրում"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Ցուցադրե՞լ ձեր էկրանը <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածով"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Ցուցադրել մեկ հավելված"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Ցուցադրել ամբողջ էկրանը"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Ցուցադրել մեկ հավելված"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Ցուցադրել ամբողջ էկրանը"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Երբ ցուցադրում եք ամբողջ էկրանը, տեսանելի կլինի այն ամենը, ինչ ձեր էկրանին տեսանելի է <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածին։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Երբ դուք որևէ հավելված եք հեռարձակում, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> հավելվածին տեսանելի կլինի այն ամենը, ինչ ցուցադրվում կամ նվագարկվում է այդ հավելվածում։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ցուցադրել էկրանը"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Արբանյակային լավ կապ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Հասանելի է արբանյակային կապ"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Շտապ կանչեր կամ SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Աշխատանքային պրոֆիլ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Զվարճանք մեկ՝ որոշակի մարդու համար"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Համակարգի ՕՄ-ի կարգավորիչը հնարավորություն է տալիս հարմարեցնել Android-ի օգտատիրոջ միջերեսը: Այս փորձնական գործառույթները կարող են հետագա թողարկումների մեջ փոփոխվել, խափանվել կամ ընդհանրապես չհայտնվել: Եթե շարունակում եք, զգուշացեք:"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ծալել պատկերակը"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ծավալել պատկերակը"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"կամ"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"«Հետ» ժեստ"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Հիմնական էկրան անցնելու ժեստ"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Գործողության ստեղն"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index d5f766b..8c58012 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> dan aplikasi terbuka lainnya mendeteksi screenshot ini."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Tambahkan ke catatan"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Sertakan link"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Perekam Layar"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Memproses perekaman layar"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifikasi yang sedang berjalan untuk sesi rekaman layar"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Screensaver"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Jangan Ganggu"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Mode prioritas"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Perangkat yang disandingkan tak tersedia"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Ketuk untuk mulai atau berhenti menghubungkan perangkat"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Gunakan Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Terhubung"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Berbagi Audio"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Ketuk untuk beralih atau berbagi audio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Disimpan"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"berhenti hubungkan"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktifkan"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Buka Setelan"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Perangkat lainnya"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aktifkan Ringkasan"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Mode prioritas"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Selesai"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Setelan"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Aktif"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Layanan yang menyediakan fungsi ini akan memiliki akses ke semua informasi yang terlihat di layar atau diputar dari perangkat saat merekam atau melakukan transmisi. Ini mencakup informasi seperti sandi, detail pembayaran, foto, pesan, dan audio yang Anda putar."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Bagikan atau rekam aplikasi"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Bagikan layar dengan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Bagikan satu aplikasi"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Bagikan seluruh layar"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Bagikan satu aplikasi"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Bagikan seluruh layar"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"JIka Anda membagikan seluruh layar, semua hal yang ada di layar Anda akan terlihat oleh <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Jika Anda membagikan aplikasi, semua hal yang ditampilkan atau diputar di aplikasi tersebut akan terlihat oleh <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Bagikan layar"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, koneksi baik"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, koneksi tersedia"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via Satelit"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Panggilan darurat atau SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil kerja"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Tidak semua orang menganggapnya baik"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Penyetel Antarmuka Pengguna Sistem memberikan cara tambahan untuk mengubah dan menyesuaikan antarmuka pengguna Android. Fitur eksperimental ini dapat berubah, rusak, atau menghilang dalam rilis di masa mendatang. Lanjutkan dengan hati-hati."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikon ciutkan"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikon luaskan"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"atau"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gestur kembali"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gestur layar utama"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tombol tindakan"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index b3291bb..6b3b6732 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> og önnur opin forrit greindu skjámyndina."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Bæta við glósu"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Hafa tengil með"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Skjáupptaka"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Vinnur úr skjáupptöku"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Áframhaldandi tilkynning fyrir skjáupptökulotu"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Skjávari"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ónáðið ekki"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Forgangsstillingar"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Engin pöruð tæki til staðar"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Ýttu til að tengja eða aftengja tæki"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Nota Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Tengt"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Hljóði deilt"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Ýttu til að skipta um eða deila hljóði"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Vistað"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"aftengja"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"virkja"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Opna stillingar"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Annað tæki"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Kveikja/slökkva á yfirliti"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Forgangsstillingar"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Lokið"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Stillingar"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Kveikt"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Þjónustan sem býður upp á þennan eiginleika fær aðgang að öllum upplýsingum sem sjást á skjánum eða eru spilaðar í tækinu á meðan upptaka eða vörpun er í gangi, þar á meðal aðgangsorði, greiðsluupplýsingum, myndum, skilaboðum og hljóðefni sem þú spilar."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Deila eða taka upp forrit"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Deila skjánum með <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Deila einu forriti"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Deila öllum skjánum"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Deila einu forriti"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Deila öllum skjánum"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Þegar þú deilir öllum skjánum verður allt á skjánum sýnilegt <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og vídeó."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Þegar þú deilir forriti er allt sem sést eða er spilað í því forriti sýnilegt <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og vídeó."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Deila skjá"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Gervihnöttur, góð tenging"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Gervihnöttur, tenging tiltæk"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Gervihnattar-SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Neyðarsímtöl eða SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Vinnusnið"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Þetta er ekki allra"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Fínstillingar kerfisviðmóts gera þér kleift að fínstilla og sérsníða notendaviðmót Android. Þessir tilraunaeiginleikar geta breyst, bilað eða horfið í síðari útgáfum. Gakktu því hægt um gleðinnar dyr."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Minnka tákn"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Stækka tákn"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"eða"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Bending til að fara til baka"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Bending til að fara á upphafsskjá"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Aðgerðalykill"</string>
diff --git a/packages/SystemUI/res/values-it-feminine/strings.xml b/packages/SystemUI/res/values-it-feminine/strings.xml
index 99b9361..e8dbc40 100644
--- a/packages/SystemUI/res/values-it-feminine/strings.xml
+++ b/packages/SystemUI/res/values-it-feminine/strings.xml
@@ -21,5 +21,4 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="zen_priority_introduction" msgid="3159291973383796646">"Non verrai disturbata da suoni e vibrazioni, ad eccezione di sveglie, promemoria, eventi, chiamate da contatti da te specificati ed elementi che hai scelto di continuare a riprodurre, inclusi video, musica e giochi."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Non verrai disturbata da suoni e vibrazioni, ad eccezione delle sveglie. Potrai comunque sentire qualunque cosa decidi di riprodurre, inclusi video, musica e giochi."</string>
- <string name="empty_user_name" msgid="3389155775773578300">"Amiche"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it-masculine/strings.xml b/packages/SystemUI/res/values-it-masculine/strings.xml
index 5e78889..5a76304 100644
--- a/packages/SystemUI/res/values-it-masculine/strings.xml
+++ b/packages/SystemUI/res/values-it-masculine/strings.xml
@@ -21,5 +21,4 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="zen_priority_introduction" msgid="3159291973383796646">"Non verrai disturbato da suoni e vibrazioni, ad eccezione di sveglie, promemoria, eventi, chiamate da contatti da te specificati ed elementi che hai scelto di continuare a riprodurre, inclusi video, musica e giochi."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Non verrai disturbato da suoni e vibrazioni, ad eccezione delle sveglie. Potrai comunque sentire qualunque cosa decidi di riprodurre, inclusi video, musica e giochi."</string>
- <string name="empty_user_name" msgid="3389155775773578300">"Amici"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it-neuter/strings.xml b/packages/SystemUI/res/values-it-neuter/strings.xml
index 0e1c227..09237f5 100644
--- a/packages/SystemUI/res/values-it-neuter/strings.xml
+++ b/packages/SystemUI/res/values-it-neuter/strings.xml
@@ -21,5 +21,4 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="zen_priority_introduction" msgid="3159291973383796646">"Non verrai disturbatə da suoni e vibrazioni, ad eccezione di sveglie, promemoria, eventi, chiamate da contatti da te specificati ed elementi che hai scelto di continuare a riprodurre, inclusi video, musica e giochi."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"Non verrai disturbatə da suoni e vibrazioni, ad eccezione delle sveglie. Potrai comunque sentire qualunque cosa decidi di riprodurre, inclusi video, musica e giochi."</string>
- <string name="empty_user_name" msgid="3389155775773578300">"Amicɜ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index b37eff9..958d67b 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4811759950673118541">"UI sistema"</string>
+ <string name="app_label" msgid="4811759950673118541">"UI di sistema"</string>
<string name="battery_low_title" msgid="5319680173344341779">"Attivare il risparmio energetico?"</string>
<string name="battery_low_description" msgid="3282977755476423966">"Batteria rimanente: <xliff:g id="PERCENTAGE">%s</xliff:g>. Il risparmio energetico attiva il tema scuro, limita l\'attività in background e ritarda le notifiche."</string>
<string name="battery_low_intro" msgid="5148725009653088790">"Il risparmio energetico attiva il tema scuro, limita l\'attività in background e ritarda le notifiche."</string>
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> e altre app aperte hanno rilevato questo screenshot."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Aggiungi alla nota"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Includi link"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Registrazione dello schermo"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Elaborazione registrazione…"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifica costante per una sessione di registrazione dello schermo"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Salvaschermo"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Non disturbare"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modalità priorità"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Nessun dispositivo accoppiato disponibile"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tocca per connettere o disconnettere un dispositivo"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Usa il Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Dispositivo connesso"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Condivisione audio"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tocca per cambiare o condividere l\'audio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Dispositivo salvato"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnetti"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"attiva"</string>
@@ -390,7 +393,7 @@
<string name="performance" msgid="6552785217174378320">"Prestazioni"</string>
<string name="user_interface" msgid="3712869377953950887">"Interfaccia utente"</string>
<string name="thermal" msgid="6758074791325414831">"Termico"</string>
- <string name="custom" msgid="3337456985275158299">"Personalizzate"</string>
+ <string name="custom" msgid="3337456985275158299">"Personalizzata"</string>
<string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Impostazioni di traccia personalizzate"</string>
<string name="restore_default" msgid="5259420807486239755">"Ripristina predefinite"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modalità a una mano"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Apri Impostazioni"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Altro dispositivo"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Attiva/disattiva la panoramica"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modalità priorità"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Fine"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Impostazioni"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"On"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Il servizio che offre questa funzione avrà accesso a tutte le informazioni visibili sul tuo schermo o riprodotte dal tuo dispositivo durante la registrazione o la trasmissione. Sono incluse informazioni quali password, dettagli sui pagamenti, foto, messaggi e audio riprodotto."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Condividi o registra un\'app"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Condividere lo schermo con <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Condividi un\'app"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Condividi schermo intero"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Condividi un\'app"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Condividi schermo intero"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Quando condividi lo schermo intero, tutto ciò che è nella schermata è visibile a <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Presta quindi attenzione a password, dati di pagamento, messaggi, foto, audio e video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Quando condividi un\'app, tutto ciò che viene mostrato o riprodotto al suo interno è visibile a <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Presta quindi attenzione a password, dati di pagamento, messaggi, foto, audio e video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Condividi schermo"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellitare, connessione buona"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellitare, connessione disponibile"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS satellitare"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Chiamate di emergenza o SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profilo di lavoro"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Il divertimento riservato a pochi eletti"</string>
<string name="tuner_warning" msgid="1861736288458481650">"L\'Ottimizzatore UI di sistema mette a disposizione altri metodi per modificare e personalizzare l\'interfaccia utente di Android. Queste funzioni sperimentali potrebbero cambiare, interrompersi o scomparire nelle versioni successive. Procedi con cautela."</string>
@@ -1214,7 +1221,7 @@
<string name="video_status" msgid="4548544654316843225">"Visione in corso"</string>
<string name="audio_status" msgid="4237055636967709208">"Ascolto in corso"</string>
<string name="game_status" msgid="1340694320630973259">"Gioco in corso"</string>
- <string name="empty_user_name" msgid="3389155775773578300">"Persone amiche"</string>
+ <string name="empty_user_name" msgid="3389155775773578300">"Amico"</string>
<string name="empty_status" msgid="5938893404951307749">"Chattiamo stasera."</string>
<string name="status_before_loading" msgid="1500477307859631381">"I contenuti verranno mostrati a breve"</string>
<string name="missed_call" msgid="4228016077700161689">"Chiamata persa"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icona Comprimi"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icona Espandi"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"oppure"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto Indietro"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto Home"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tasto azione"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index ecb8409..1161fa0 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"האפליקציה <xliff:g id="APPNAME">%1$s</xliff:g> ואפליקציות פתוחות נוספות זיהו את צילום המסך הזה."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"הוספה לפתק"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"הכנסת הקישור"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"מקליט המסך"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"מתבצע עיבוד של הקלטת מסך"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"התראה מתמשכת לסשן הקלטת מסך"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"שומר מסך"</string>
<string name="ethernet_label" msgid="2203544727007463351">"אתרנט"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"נא לא להפריע"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"מצבי עדיפות"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"אין מכשירים מותאמים זמינים"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"אפשר להקיש כדי להתחבר למכשיר או להתנתק ממנו"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"שימוש ב-Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"מחובר"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"שיתוף אודיו"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"צריך להקיש כדי להחליף מצב או לשתף אודיו"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"נשמר"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ניתוק"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"הפעלה"</string>
@@ -380,8 +383,8 @@
<string name="quick_settings_screen_record_label" msgid="8650355346742003694">"הקלטת המסך"</string>
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"התחלה"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"עצירה"</string>
- <string name="qs_record_issue_label" msgid="8166290137285529059">"תיעוד הבעיה"</string>
- <string name="qs_record_issue_start" msgid="2979831312582567056">"התחלה"</string>
+ <string name="qs_record_issue_label" msgid="8166290137285529059">"תיעוד בעיה"</string>
+ <string name="qs_record_issue_start" msgid="2979831312582567056">"קדימה"</string>
<string name="qs_record_issue_stop" msgid="3531747965741982657">"עצירה"</string>
<string name="qs_record_issue_bug_report" msgid="8229031766918650079">"דיווח על באג"</string>
<string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"איזה חלק בחוויית השימוש שלך במכשיר הושפע?"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"פתיחת ההגדרות"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"מכשיר אחר"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"החלפת מצב של מסכים אחרונים"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"מצבי עדיפות"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"סיום"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"הגדרות"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"מצב מופעל"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"לשירות שמספק את הפונקציה הזו תהיה גישה לכל הפרטים שגלויים במסך שלך או מופעלים מהמכשיר שלך בזמן הקלטה או הפעלת Cast – כולל פרטים כמו סיסמאות, פרטי תשלום, תמונות, הודעות ואודיו שמושמע מהמכשיר."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"שיתוף או הקלטה של אפליקציה"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"לשתף את המסך שלך עם <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"שיתוף של אפליקציה אחת"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"שיתוף כל המסך"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"שיתוף של אפליקציה אחת"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"שיתוף כל המסך"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"כשמשתפים את כל המסך, כל מה שמופיע בו יהיה גלוי ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"כשמשתפים אפליקציה, כל מה שרואים או מפעילים בה יהיה גלוי ל-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"שיתוף המסך"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"לוויין, חיבור באיכות טובה"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"לוויין, יש חיבור זמין"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"תקשורת לוויינית למצב חירום"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"שיחות חירום או SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"פרופיל עבודה"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"מהנה בשביל חלק מהאנשים, אבל לא בשביל כולם"</string>
<string name="tuner_warning" msgid="1861736288458481650">"התכונה System UI Tuner מספקת לך דרכים נוספות להתאים אישית את ממשק המשתמש של Android. התכונות הניסיוניות האלה עשויות להשתנות, לא לעבוד כראוי או להיעלם בגרסאות עתידיות. יש להמשיך בזהירות."</string>
@@ -996,7 +1003,7 @@
<string name="slice_permission_text_1" msgid="6675965177075443714">"- תהיה לה אפשרות לקרוא מידע מאפליקציית <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="slice_permission_text_2" msgid="6758906940360746983">"- תהיה לה יכולת לנקוט פעולה בתוך <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="slice_permission_checkbox" msgid="4242888137592298523">"יש לאשר לאפליקציית <xliff:g id="APP">%1$s</xliff:g> להראות חלקים מכל אפליציה שהיא"</string>
- <string name="slice_permission_allow" msgid="6340449521277951123">"אני רוצה לאשר"</string>
+ <string name="slice_permission_allow" msgid="6340449521277951123">"אישור"</string>
<string name="slice_permission_deny" msgid="6870256451658176895">"אני לא מרשה"</string>
<string name="auto_saver_title" msgid="6873691178754086596">"יש להקיש כדי לתזמן את מצב החיסכון בסוללה"</string>
<string name="auto_saver_text" msgid="3214960308353838764">"מומלץ להפעיל את התכונה כשיש סבירות גבוהה שהסוללה תתרוקן"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"סמל הכיווץ"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"סמל ההרחבה"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"או"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"תנועת חזרה"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"תנועת חזרה למסך הבית"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"מקש הפעולה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 98d320d..6436cdd 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> とその他の開いているアプリがこのスクリーンショットを検出しました。"</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"メモに追加"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"リンクを含める"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"スクリーン レコーダー"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"画面の録画を処理しています"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"画面の録画セッション中の通知"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"スクリーン セーバー"</string>
<string name="ethernet_label" msgid="2203544727007463351">"イーサネット"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"サイレント モード"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"優先モード"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ペア設定されたデバイスがありません"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"タップしてデバイスを接続または接続解除します"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth を使用"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"接続しました"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"音声の共有"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"タップして音声の切り替えや共有を行えます"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"保存済み"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"接続を解除"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"有効化"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"設定を開く"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"その他のデバイス"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"概要を切り替え"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"優先モード"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"完了"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"設定"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"ON"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"この機能を提供するサービスは、録画中またはキャスト中に画面上に表示または再生される情報のすべてにアクセスできるようになります。これには、パスワード、お支払いの詳細、写真、メッセージ、音声などが含まれます。"</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"アプリの共有または録画"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> と画面を共有しますか?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"1 つのアプリを共有"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"画面全体を共有"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"1 個のアプリを共有"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"画面全体を共有"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"画面全体を共有すると、画面に表示される内容が <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> にすべて公開されます。パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"アプリを共有すると、そのアプリで表示または再生される内容が <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> にすべて公開されます。パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"画面を共有"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"衛生、接続状態良好"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"衛生、接続利用可能"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"衛星 SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"緊急通報または SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"仕事用プロファイル"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"一部の方のみお楽しみいただける限定公開ツール"</string>
<string name="tuner_warning" msgid="1861736288458481650">"システムUI調整ツールでは、Androidユーザーインターフェースの調整やカスタマイズを行えます。これらの試験運用機能は今後のリリースで変更となったり、中止となったり、削除されたりする可能性がありますのでご注意ください。"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"閉じるアイコン"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"開くアイコン"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"または"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"「戻る」ジェスチャー"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"「ホーム」ジェスチャー"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"アクションキー"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index d85d7c1..7d52760 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g>-მა და სხვა გახსნილმა აპებმა აღმოაჩინეს ეკრანის ეს ანაბეჭდი."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"დაამატეთ შენიშვნა"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"ბმულის დართვა"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"ეკრანის ჩამწერი"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ეკრანის ჩანაწერი მუშავდება"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"უწყვეტი შეტყობინება ეკრანის ჩაწერის სესიისთვის"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"ეკრანმზოგი"</string>
<string name="ethernet_label" msgid="2203544727007463351">"ეთერნეტი"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"არ შემაწუხოთ"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"პრიორიტეტული რეჟიმები"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"დაწყვილებული მოწყობილობები მიუწვდომელია"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"შეეხეთ მოწყობილობის დასაკავშირებლად ან გასათიშად"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth-ის გამოყენება"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"დაკავშირებული"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"აუდიოს გაზიარება"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"შეეხეთ აუდიოს გადასართავად ან გასაზიარებლად"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"შენახული"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"კავშირის გაწყვეტა"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"გააქტიურება"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"პარამეტრების გახსნა"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"სხვა მოწყობილობა"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"მიმოხილვის გადართვა"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"პრიორიტეტული რეჟიმები"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"მზადაა"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"პარამეტრები"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"ჩართული"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ამ ფუნქციის მომწოდებელ სერვისს ექნება წვდომა ყველა ინფორმაციაზე, რომელიც თქვენს ეკრანზე გამოჩნდება ან თქვენს მოწყობილობაზე დაიკვრება ჩაწერის ან ტრანსლირების განმავლობაში. აღნიშნული მოიცავს ისეთ ინფორმაციას, როგორიც არის პაროლები, გადახდის დეტალები, ფოტოები, შეტყობინებები და თქვენ მიერ დაკრული აუდიო."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"აპის გაზიარება ან ჩაწერა"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"გსურთ თქვენი ეკრანის <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-თან გაზიარება?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ერთი აპის გაზიარება"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"მთლიანი ეკრანის გაზიარება"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"ერთი აპის გაზიარება"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"მთლიანი ეკრანის გაზიარება"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"მთლიანი ეკრანის გაზიარებისას <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ხედავს ყველაფერს, რაც თქვენს ეკრანზეა. ამიტომ სიფრთხილე გამოიჩინეთ ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"აპის გაზიარებისას <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ხედავს ყველაფერს, რაც ჩანს ან უკრავს ამ აპში. ამიტომ სიფრთხილე გამოიჩინეთ ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"ეკრანის გაზიარება"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"კარგი სატელიტური კავშირი"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ხელმისაწვდომია სატელიტური კავშირი"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"სატელიტური SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"გადაუდებელი ზარი ან SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"სამსახურის პროფილი"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ზოგისთვის გასართობია, მაგრამ არა ყველასთვის"</string>
<string name="tuner_warning" msgid="1861736288458481650">"სისტემის UI ტუნერი გაძლევთ დამატებით გზებს Android-ის სამომხმარებლო ინტერფეისის პარამეტრების დაყენებისთვის. ეს ექსპერიმენტული მახასიათებლები შეიძლება შეიცვალოს, შეწყდეს ან გაქრეს მომავალ ვერსიებში. სიფრთხილით გააგრძელეთ."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ხატულის ჩაკეცვა"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ხატულის გაფართოება"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ან"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"უკან დაბრუნების ჟესტი"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"მთავარ ეკრანზე გადასვლის ჟესტი"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"მოქმედების კლავიში"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 7a43b4b..7b32db1 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> және басқа да ашық қолданбалар осы скриншотты анықтады."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Ескертпеге қосу"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Сілтеме қосу"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Экран жазғыш"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Экран жазғыш бейнесін өңдеу"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Экранды бейнеге жазудың ағымдағы хабарландыруы"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Скринсейвер"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Этернет"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Мазаламау"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Басымдық режимдері"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Жұптасқан құрылғылар жоқ"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Құрылғыны жалғау не ажырату үшін түртіңіз."</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth-ты пайдалану"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Қосылды"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Аудио бөлісу"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Аудионы бөлісу немесе ауыстыру үшін түртіңіз."</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сақталды"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ажырату"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"іске қосу"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Параметрлерді ашу"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Басқа құрылғы"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Шолуды қосу/өшіру"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Басымдық режимдері"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Дайын"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Параметрлер"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Қосулы"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Осы функцияны ұсынатын қызмет экранда көрсетілетін немесе жазу не трансляциялау кезінде құрылғыда ойнатылған барлық ақпаратты пайдалана алады. Бұған құпия сөздер, төлем туралы мәліметтер, суреттер, хабарлар және ойнатылатын аудио сияқты ақпарат кіреді."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Қолданба экранын бөлісу не жазу"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Экранды <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> қолданбасымен бөлісу керек пе?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Бір қолданбаны бөлісу"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Бүкіл экранды бөлісу"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Бір қолданбаны бөлісу"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Бүкіл экранды бөлісу"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Бүкіл экранды бөліскен кезде, ондағы барлық контент <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> қолданбасында көрсетіледі. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды, фотосуреттерді және аудио мен бейнені ашқанда сақ болыңыз."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Қолданбаны бөліскен кезде, онда көрінетін не ойнатылатын барлық контент <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> қолданбасында көрсетіледі. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды, фотосуреттерді және аудио мен бейнені ашқанда сақ болыңыз."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Экранды бөлісу"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Жерсерік, байланыс жақсы."</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Жерсерік, байланыс бар."</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Құтқару қызметіне қоңырау шалу немесе SOS сигналын жіберу"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Жұмыс профилі"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Кейбіреулерге қызық, бірақ барлығына емес"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Жүйелік пайдаланушылық интерфейс тюнері Android пайдаланушылық интерфейсін реттеудің қосымша жолдарын береді. Бұл эксперименттік мүмкіндіктер болашақ шығарылымдарда өзгеруі, бұзылуы немесе жоғалуы мүмкін. Сақтықпен жалғастырыңыз."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Жию белгішесі"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Жаю белгішесі"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"немесе"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Артқа қайтару қимылы"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Негізгі бетке қайтару қимылы"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Әрекет пернесі"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 2319623..81664ca 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> និងកម្មវិធីដែលបើកផ្សេងទៀតបានរកឃើញរូបថតអេក្រង់នេះ។"</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"បញ្ចូលទៅក្នុងកំណត់ចំណាំ"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"រួមបញ្ចូលតំណ"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"មុខងារថតវីដេអូអេក្រង់"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"កំពុងដំណើរការការថតអេក្រង់"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ការជូនដំណឹងដែលកំពុងដំណើរការសម្រាប់រយៈពេលប្រើការថតសកម្មភាពអេក្រង់"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"ធាតុរក្សាអេក្រង់"</string>
<string name="ethernet_label" msgid="2203544727007463351">"អ៊ីសឺរណិត"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"កុំរំខាន"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"មុខងារអាទិភាព"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ប៊្លូធូស"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"មិនមានឧបករណ៍ផ្គូផ្គងដែលអាចប្រើបាន"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"ចុចដើម្បីភ្ជាប់ ឬផ្ដាច់ឧបករណ៍"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ប្រើប៊្លូធូស"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"បានភ្ជាប់"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ការស្ដាប់សំឡេងរួមគ្នា"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ចុចដើម្បីប្ដូរ ឬចែករំលែកសំឡេង"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"បានរក្សាទុក"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ផ្ដាច់"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"បើកដំណើរការ"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"បើកការកំណត់"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"ឧបករណ៍ផ្សេងទៀត"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"បិទ/បើកទិដ្ឋភាពរួម"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"មុខងារអាទិភាព"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"រួចរាល់"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ការកំណត់"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"បើក"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"សេវាកម្មដែលផ្ដល់មុខងារនេះនឹងមានសិទ្ធិចូលប្រើព័ត៌មានទាំងអស់ដែលអាចមើលឃើញនៅលើអេក្រង់របស់អ្នក ឬចាក់ពីឧបករណ៍របស់អ្នក នៅពេលកំពុងថត ឬភ្ជាប់។ ព័ត៌មាននេះមានដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ រូបថត សារ និងសំឡេងដែលអ្នកចាក់ជាដើម។"</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"ចែករំលែក ឬថតកម្មវិធី"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"បង្ហាញអេក្រង់របស់អ្នកជាមួយ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ឬ?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"បង្ហាញកម្មវិធីមួយ"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"បង្ហាញអេក្រង់ទាំងមូល"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"បង្ហាញកម្មវិធីមួយ"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"បង្ហាញអេក្រង់ទាំងមូល"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"នៅពេលអ្នកបង្ហាញអេក្រង់ទាំងមូលរបស់អ្នក <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> មើលឃើញអ្វីគ្រប់យ៉ាងនៅលើអេក្រង់របស់អ្នក។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"នៅពេលអ្នកបង្ហាញកម្មវិធីណាមួយ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> មើលឃើញអ្វីគ្រប់យ៉ាងដែលបង្ហាញ ឬចាក់ក្នុងកម្មវិធីនោះ។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"បង្ហាញអេក្រង់"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ផ្កាយរណប មានការតភ្ជាប់ល្អ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ផ្កាយរណប អាចតភ្ជាប់បាន"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"ការប្រកាសអាសន្នតាមផ្កាយរណប"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ការហៅទៅលេខសង្គ្រោះបន្ទាន់ ឬ SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"កម្រងព័ត៌មានការងារ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ល្អសម្រាប់អ្នកប្រើមួយចំនួន តែមិនសម្រាប់គ្រប់គ្នាទេ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"កម្មវិធីសម្រួល UI ប្រព័ន្ធផ្តល់ជូនអ្នកនូវមធ្យោបាយបន្ថែមទៀតដើម្បីកែសម្រួល និងប្តូរចំណុចប្រទាក់អ្នកប្រើ Android តាមបំណង។ លក្ខណៈពិសេសសាកល្បងនេះអាចនឹងផ្លាស់ប្តូរ បំបែក ឬបាត់បង់បន្ទាប់ពីការចេញផ្សាយនាពេលអនាគត។ សូមបន្តដោយប្រុងប្រយ័ត្ន។"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"រូបតំណាង \"បង្រួម\""</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"រូបតំណាង \"ពង្រីក\""</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ឬ"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ចលនាថយក្រោយ"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ចលនាទៅទំព័រដើម"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"គ្រាប់ចុចសកម្មភាព"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index aeb3b1ef0..e1b119c 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -45,7 +45,7 @@
<string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಅನ್ನು ನಿಯಂತ್ರಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯುವುದೇ?\nಈ ಆ್ಯಪ್ಗೆ ರೆಕಾರ್ಡ್ ಅನುಮತಿಯನ್ನು ನೀಡಲಾಗಿಲ್ಲ, ಆದರೆ ಈ USB ಸಾಧನದ ಮೂಲಕ ಆಡಿಯೊವನ್ನು ಸೆರೆಹಿಡಿಯಬಹುದು."</string>
<string name="usb_accessory_confirm_prompt" msgid="5728408382798643421">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯುವುದೇ?"</string>
<string name="usb_accessory_uri_prompt" msgid="6756649383432542382">"ಆಪ್ಗಳು USB ಪರಿಕರದಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸುವುದಿಲ್ಲ. ಆ ಬಗ್ಗೆ <xliff:g id="URL">%1$s</xliff:g> ನಲ್ಲಿ ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string>
- <string name="title_usb_accessory" msgid="1236358027511638648">"USB ಪರಿಕರ"</string>
+ <string name="title_usb_accessory" msgid="1236358027511638648">"USB ಆ್ಯಕ್ಸೆಸರಿ"</string>
<string name="label_view" msgid="6815442985276363364">"ವೀಕ್ಷಿಸು"</string>
<string name="always_use_device" msgid="210535878779644679">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಸಂಪರ್ಕಗೊಂಡಾಗ ಯಾವಾಗಲೂ <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯಿರಿ"</string>
<string name="always_use_accessory" msgid="1977225429341838444">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ಸಂಪರ್ಕಗೊಂಡಾಗ ಯಾವಾಗಲೂ <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯಿರಿ"</string>
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ಹಾಗೂ ತೆರೆದಿರುವ ಇತರ ಆ್ಯಪ್ಗಳು ಈ ಸ್ಕ್ರೀನ್ಶಾಟ್ ಅನ್ನು ಪತ್ತೆಹಚ್ಚಿವೆ."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"ಟಿಪ್ಪಣಿಗೆ ಸೇರಿಸಿ"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"ಲಿಂಕ್ ಅನ್ನು ಸೇರಿಸಿ"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡರ್"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಆಗುತ್ತಿದೆ"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಸೆಶನ್ಗಾಗಿ ಚಾಲ್ತಿಯಲ್ಲಿರುವ ನೋಟಿಫಿಕೇಶನ್"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"ಸ್ಕ್ರೀನ್ ಸೇವರ್"</string>
<string name="ethernet_label" msgid="2203544727007463351">"ಇಥರ್ನೆಟ್"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"ಆದ್ಯತೆಯ ಮೋಡ್ಗಳು"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ಬ್ಲೂಟೂತ್"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ಯಾವುದೇ ಜೋಡಿಸಲಾದ ಸಾಧನಗಳು ಲಭ್ಯವಿಲ್ಲ"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"ಸಾಧನವನ್ನು ಕನೆಕ್ಟ್ ಅಥವಾ ಡಿಸ್ಕನೆಕ್ಟ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ಬ್ಲೂಟೂತ್ ಬಳಸಿ"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆ"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ಆಡಿಯೊವನ್ನು ಬದಲಾಯಿಸಲು ಅಥವಾ ಹಂಚಿಕೊಳ್ಳಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ಸೇವ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ಡಿಸ್ಕನೆಕ್ಟ್ ಮಾಡಿ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ತೆರೆಯಿರಿ"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"ಅನ್ಯ ಸಾಧನ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ಟಾಗಲ್ ನ ಅವಲೋಕನ"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ಆದ್ಯತೆಯ ಮೋಡ್ಗಳು"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"ಮುಗಿದಿದೆ"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"ಆನ್ ಆಗಿದೆ"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ಈ ಕಾರ್ಯವನ್ನು ಒದಗಿಸುವ ಸೇವೆಗಳು, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಗೋಚರಿಸುವ ಅಥವಾ ರೆಕಾರ್ಡಿಂಗ್ ಮಾಡುವಾಗ ಅಥವಾ ಕ್ಯಾಸ್ಟ್ ಮಾಡುವಾಗ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡುವ ಎಲ್ಲಾ ಮಾಹಿತಿಗಳಿಗೆ ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತವೆ. ಇದು ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಫೋಟೋಗಳು, ಸಂದೇಶಗಳು ಮತ್ತು ನೀವು ಪ್ಲೇ ಮಾಡುವ ಆಡಿಯೊದಂತಹ ಮಾಹಿತಿಯನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"ಆ್ಯಪ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ ಅಥವಾ ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಅನ್ನು <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ನೊಂದಿಗೆ ಹಂಚಿಕೊಳ್ಳಬೇಕೇ?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ಒಂದು ಆ್ಯಪ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"ಸಂಪೂರ್ಣ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"ಒಂದು ಆ್ಯಪ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"ಸಂಪೂರ್ಣ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"ನಿಮ್ಮ ಸಂಪೂರ್ಣ ಸ್ಕ್ರೀನ್ ಅನ್ನು ನೀವು ಹಂಚಿಕೊಳ್ಳುತ್ತಿರುವಾಗ, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ನಲ್ಲಿರುವ ಏನಾದರೂ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಗೆ ಗೋಚರಿಸುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಮತ್ತು ಆಡಿಯೋ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಬಗ್ಗೆ ಜಾಗರೂಕರಾಗಿರಿ."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳುತ್ತಿರುವಾಗ, ಆ ಆ್ಯಪ್ನಲ್ಲಿ ತೋರಿಸಿರುವ ಅಥವಾ ಪ್ಲೇ ಮಾಡಿದ ಏನಾದರೂ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ಗೆ ಗೋಚರಿಸುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಮತ್ತು ಆಡಿಯೋ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಬಗ್ಗೆ ಜಾಗರೂಕರಾಗಿರಿ."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"ಸ್ಕ್ರೀನ್ ಹಂಚಿಕೊಳ್ಳಿ"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ಸ್ಯಾಟಲೈಟ್, ಕನೆಕ್ಷನ್ ಉತ್ತಮವಾಗಿದೆ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ಸ್ಯಾಟಲೈಟ್, ಕನೆಕ್ಷನ್ ಲಭ್ಯವಿದೆ"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"ಸ್ಯಾಟಲೈಟ್ SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ತುರ್ತು ಕರೆಗಳು ಅಥವಾ SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ಕೆಲಸದ ಪ್ರೊಫೈಲ್"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ಕೆಲವರಿಗೆ ಮೋಜು ಆಗಿದೆ ಎಲ್ಲರಿಗೆ ಇಲ್ಲ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"ಸಿಸ್ಟಂ UI ಟ್ಯೂನರ್ ನಿಮಗೆ Android ಬಳಕೆದಾರ ಅಂತರಸಂಪರ್ಕವನ್ನು ಸರಿಪಡಿಸಲು ಮತ್ತು ಕಸ್ಟಮೈಸ್ ಮಾಡಲು ಹೆಚ್ಚುವರಿ ಮಾರ್ಗಗಳನ್ನು ನೀಡುತ್ತದೆ. ಈ ಪ್ರಾಯೋಗಿಕ ವೈಶಿಷ್ಟ್ಯಗಳು ಭವಿಷ್ಯದ ಬಿಡುಗಡೆಗಳಲ್ಲಿ ಬದಲಾಗಬಹುದು, ವಿರಾಮವಾಗಬಹುದು ಅಥವಾ ಕಾಣಿಸಿಕೊಳ್ಳದಿರಬಹುದು. ಎಚ್ಚರಿಕೆಯಿಂದ ಮುಂದುವರಿಯಿರಿ."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ಕುಗ್ಗಿಸುವ ಐಕಾನ್"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ವಿಸ್ತೃತಗೊಳಿಸುವ ಐಕಾನ್"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ಅಥವಾ"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ಹಿಂಬದಿ ಗೆಸ್ಚರ್"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ಹೋಮ್ ಗೆಸ್ಚರ್"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ಆ್ಯಕ್ಷನ್ ಕೀ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 277582c..27aa785 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> 및 기타 공개 앱에서 이 스크린샷을 감지했습니다."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"메모에 추가"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"링크 포함"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g><xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"화면 녹화"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"화면 녹화 처리 중"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"화면 녹화 세션에 관한 지속적인 알림"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"화면 보호기"</string>
<string name="ethernet_label" msgid="2203544727007463351">"이더넷"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"방해 금지 모드"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"우선순위 모드"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"블루투스"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"페어링된 기기가 없습니다"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"기기를 연결 또는 연결 해제하려면 탭하세요"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"블루투스 사용"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"연결됨"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"오디오 공유"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"오디오를 전환하거나 공유하려면 탭하세요"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"저장됨"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"연결 해제"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"실행"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"설정 열기"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"기타 기기"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"최근 사용 버튼 전환"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"우선순위 모드"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"완료"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"설정"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"사용"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"이 기능을 제공하는 서비스는 녹화 또는 전송 중에 화면에 표시되거나 기기에서 재생되는 모든 정보에 액세스할 수 있습니다. 여기에는 비밀번호, 결제 세부정보, 사진, 메시지, 사용자가 재생하는 오디오 등의 정보가 포함됩니다."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"앱 공유 또는 녹화"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"화면을 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> 앱과 공유하시겠습니까?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"앱 하나 공유"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"전체 화면 공유"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"앱 하나 공유"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"전체 화면 공유"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"전체 화면을 공유하면 화면에 있는 모든 항목이 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>에 표시됩니다. 따라서 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"앱을 공유하면 앱에 표시되거나 앱에서 재생되는 모든 항목이 <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>에 표시됩니다. 따라서 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"화면 공유"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"위성, 연결 상태 양호"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"위성, 연결 가능"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"위성 긴급 SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"긴급 전화 또는 SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"직장 프로필"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"마음에 들지 않을 수도 있음"</string>
<string name="tuner_warning" msgid="1861736288458481650">"시스템 UI 튜너를 사용하면 Android 사용자 인터페이스를 변경 및 맞춤설정할 수 있습니다. 이러한 실험실 기능은 향후 출시 버전에서는 변경되거나 다운되거나 사라질 수 있습니다. 신중하게 진행하시기 바랍니다."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"접기 아이콘"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"확장 아이콘"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"또는"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"뒤로 동작"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"홈 동작"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"작업 키"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 4680236..306baa7 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -104,13 +104,14 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> жана ачылып турган башка колдонмолор ушул скриншотту аныктады."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Кыска жазууга кошуу"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Шилтеме кошуу"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Экрандан видео жаздырып алуу"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Экрандан жаздырылып алынган видео иштетилүүдө"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Экранды жаздыруу сеансы боюнча учурдагы билдирме"</string>
<string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Экранды жаздырасызбы?"</string>
<string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Бир колдонмону жаздыруу"</string>
<string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="2794896384693120020">"Бүтүндөй экранды жаздыруу"</string>
- <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Бүт экранды жаздырганда экранда көрүнүп турган нерселердин баары жаздырылат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string>
+ <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Бүтүндөй экранды жаздырганда, андагы нерселердин баары видеого түшүп калат. Андыктан этият болуп, сырсөздөр, төлөм ыкмалары, билдирүүлөр, сүрөттөр, аудио жана видео материалдар сыяктуу купуя нерселерди көрсөтүп албаңыз."</string>
<string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Колдонмону жаздырганда ал колдонмодо көрсөтүлүп же ойнотулуп жаткан нерселер жаздырылат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string>
<string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Экранды жаздыруу"</string>
<string name="screenrecord_app_selector_title" msgid="3854492366333954736">"Жаздыруу үчүн колдонмо тандоо"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Көшөгө"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Тынчымды алба"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Маанилүүлүк режимдери"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Жупташкан түзмөктөр жок"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Түзмөктү туташтыруу же ажыратуу үчүн таптаңыз"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Иштетүү"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Туташты"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Чогуу угуу"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Аудиону которуштуруу же бөлүшүү үчүн таптаңыз"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сакталды"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ажыратуу"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"иштетүү"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Параметрлерди ачуу"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Башка түзмөк"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Назар режимин өчүрүү/күйгүзүү"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Маанилүүлүк режимдери"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Бүттү"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Параметрлер"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Күйүк"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Жаздырып же тышкы экранга чыгарып жатканда кызмат көрсөтүүчү экраныңыздагы бардык маалыматты же түзмөктө ойнотулуп жаткан нерселерди көрө алат. Буга сырсөздөр, төлөмдүн чоо-жайы, сүрөттөр, билдирүүлөр жана ойнотулган аудио кирет."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Колдонмону бөлүшүү же жаздыруу"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Экранды <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> менен бөлүшөсүзбү?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Бир колдонмону бөлүшүү"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Толук экранды бөлүшүү"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Бир колдонмону бөлүшүү"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Толук экранды бөлүшүү"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Бүтүндөй экранды бөлүшкөндө андагы бардык нерселер <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> колдонмосуна көрүнөт. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Колдонмону бөлүшкөндө ал колдонмодо көрсөтүлүп же ойнотулуп жаткан нерселер <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> колдонмосуна көрүнөт. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Экранды бөлүшүү"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Спутник, байланыш жакшы"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Спутник, байланыш бар"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Спутник SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Шашылыш чалуулар же SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Жумуш профили"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Баарына эле жага бербейт"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner Android колдонуучу интерфейсин жөнгө салып жана ыңгайлаштыруунун кошумча ыкмаларын сунуштайт. Бул сынамык функциялар кийинки чыгарылыштарда өзгөрүлүп, бузулуп же жоголуп кетиши мүмкүн. Абайлап колдонуңуз."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Жыйыштыруу сүрөтчөсү"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Жайып көрсөтүү сүрөтчөсү"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"же"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Артка кайтуу жаңсоосу"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Башкы бетке өтүү жаңсоосу"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Аракет баскычы"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index edb8fa3..75f579c 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ແລະ ແອັບອື່ນໆທີ່ເປີດຢູ່ກວດພົບຮູບໜ້າຈໍນີ້."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"ເພີ່ມໃສ່ບັນທຶກ"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"ຮວມລິ້ງ"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"ໂປຣແກຣມບັນທຶກໜ້າຈໍ"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ກຳລັງປະມວນຜົນການບັນທຶກໜ້າຈໍ"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ການແຈ້ງເຕືອນສຳລັບເຊດຊັນການບັນທຶກໜ້າຈໍໃດໜຶ່ງ"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"ພາບພັກໜ້າຈໍ"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"ຫ້າມລົບກວນ"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"ໂໝດຄວາມສຳຄັນ"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ບໍ່ມີອຸປະກອນທີ່ສາມາດຈັບຄູ່ໄດ້"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"ແຕະເພື່ອເຊື່ອມຕໍ່ ຫຼື ຕັດການເຊື່ອມຕໍ່ອຸປະກອນ"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ໃຊ້ Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ເຊື່ອມຕໍ່ແລ້ວ"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ການແບ່ງປັນສຽງ"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ແຕະເພື່ອສະຫຼັບ ຫຼື ແບ່ງປັນສຽງ"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ບັນທຶກແລ້ວ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ຕັດການເຊື່ອມຕໍ່"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ເປີດນຳໃຊ້"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"ເປີດການຕັ້ງຄ່າ"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"ອຸປະກອນອື່ນໆ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ສະຫຼັບພາບຮວມ"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ໂໝດຄວາມສຳຄັນ"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"ແລ້ວໆ"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ການຕັ້ງຄ່າ"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"ເປີດ"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ບໍລິການທີ່ມີຟັງຊັນນີ້ຈະມີສິດເຂົ້າເຖິງຂໍ້ມູນທັງໝົດທີ່ປາກົດຢູ່ໜ້າຈໍຂອງທ່ານ ຫຼື ຫຼິ້ນຈາກອຸປະກອນຂອງທ່ານໃນຂະນະທີ່ບັນທຶກ ຫຼື ສົ່ງສັນຍານ. ເຊິ່ງຈະຮວມທັງຂໍ້ມູນຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຮູບພາບ, ຂໍ້ຄວາມ ແລະ ສຽງທີ່ທ່ານຫຼິ້ນ."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"ແບ່ງປັນ ຫຼື ບັນທຶກແອັບ"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"ແບ່ງປັນໜ້າຈໍຂອງທ່ານກັບ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ບໍ?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ແບ່ງປັນແອັບດຽວ"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"ແບ່ງປັນໜ້າຈໍທັງໝົດ"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"ແບ່ງປັນແອັບດຽວ"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"ແບ່ງປັນໜ້າຈໍທັງໝົດ"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"ເມື່ອທ່ານແບ່ງປັນໜ້າຈໍທັງໝົດຂອງທ່ານ, ຄົນອື່ນຈະເບິ່ງເຫັນທຸກຢ່າງທີ່ຢູ່ໜ້າຈໍຂອງທ່ານໃນ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ, ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"ເມື່ອທ່ານແບ່ງປັນແອັບຂອງທ່ານ, ຄົນອື່ນຈະເບິ່ງເຫັນທຸກຢ່າງທີ່ສະແດງ ຫຼື ຫຼິ້ນໃນແອັບໃນ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ, ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"ແບ່ງປັນໜ້າຈໍ"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ດາວທຽມ, ການເຊື່ອມຕໍ່ດີ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ດາວທຽມ, ການເຊື່ອມຕໍ່ທີ່ພ້ອມນຳໃຊ້"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS ດາວທຽມ"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ໂທສຸກເສີນ ຫຼື SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ມ່ວນຊື່ນສຳລັບບາງຄົນ ແຕ່ບໍ່ແມ່ນສຳລັບທຸກຄົນ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner ໃຫ້ທ່ານມີວິທີພິເສດຕື່ມອີກໃນການປັບປ່ຽນ ແລະຕົບແຕ່ງສ່ວນຕໍ່ປະສານຜູ້ໃຊ້ຂອງ Android. ຄຸນສົມບັດທົດລອງໃຊ້ເຫຼົ່ານີ້ອາດຈະປ່ຽນແປງ, ຢຸດເຊົາ ຫຼືຫາຍໄປໃນການວາງຈຳໜ່າຍໃນອະນາຄົດ. ຈົ່ງດຳເນີນຕໍ່ດ້ວຍຄວາມລະມັດລະວັງ."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ໄອຄອນຫຍໍ້ລົງ"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ໄອຄອນຂະຫຍາຍ"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ຫຼື"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ທ່າທາງສຳລັບກັບຄືນ"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ທ່າທາງສຳລັບໜ້າຫຼັກ"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ປຸ່ມຄຳສັ່ງ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index a9a0e73..61516fe 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"„<xliff:g id="APPNAME">%1$s</xliff:g>“ ir kitos atidarytos programos aptiko šią ekrano kopiją."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Pridėti prie užrašo"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Įtraukti nuorodą"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"„<xliff:g id="APPNAME">%1$s</xliff:g>“ <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Ekrano vaizdo įrašytuvas"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Apdorojam. ekrano vaizdo įraš."</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Šiuo metu rodomas ekrano įrašymo sesijos pranešimas"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Ekrano užsklanda"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Eternetas"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Netrukdymo režimas"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioriteto režimai"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Nėra pasiekiamų susietų įrenginių"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Palieskite, kad prijungtumėte ar atjungtumėte įrenginį"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"„Bluetooth“ naudojimas"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Prisijungta"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Garso įrašų bendrinimas"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Palieskite, jei norite perjungti arba bendrinti garsą"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Išsaugota"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"atjungti"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"suaktyvinti"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Atidaryti nustatymus"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Kitas įrenginys"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Perjungti apžvalgą"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriteto režimai"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Atlikta"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nustatymai"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Įjungta"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Šią funkciją teikianti paslauga galės pasiekti visą informaciją, matomą ekrane ir leidžiamą iš įrenginio įrašant ar perduodant turinį. Tai apima įvairią informaciją, pvz., slaptažodžius, išsamią mokėjimo informaciją, nuotraukas, pranešimus ir leidžiamus garso įrašus."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Programos bendrinimas ar įrašymas"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Bendrinti ekraną su „<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Bendrinti vieną programą"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Bendrinti visą ekraną"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Bendrinti vieną programą"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Bendrinti visą ekraną"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kai bendrinate visą ekraną, „<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“ matomas visas ekrano turinys. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kai bendrinate programą, „<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>“ matomas visas toje programoje rodomas ar leidžiamas turinys. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Bendrinti ekraną"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Palydovas, geras ryšys"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Palydovas, pasiekiamas ryšys"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Prisijungimas prie palydovo kritiniu atveju"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Skambučiai pagalbos numeriu arba pagalbos iškvietimas kritiniu atveju"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Darbo profilis"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Smagu, bet ne visada"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sistemos naudotojo sąsajos derinimo priemonė suteikia papildomų galimybių pagerinti ir tinkinti „Android“ naudotojo sąsają. Šios eksperimentinės funkcijos gali pasikeisti, nutrūkti ar išnykti iš būsimų laidų. Tęskite atsargiai."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Sutraukimo piktograma"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Išskleidimo piktograma"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"arba"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Grįžimo atgal gestas"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Pagrindinio ekrano gestas"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Veiksmų klavišas"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index d1e97a6..1b48d3f 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> un citas atvērtas lietotnes konstatēja, ka tika veikts ekrānuzņēmums."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Pievienot piezīmei"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Iekļaut saiti"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Ekrāna ierakstītājs"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekrāna ieraksta apstrāde"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Aktīvs paziņojums par ekrāna ierakstīšanas sesiju"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Ekrānsaudzētājs"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Tīkls Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Režīms “Netraucēt”"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioritātes režīmi"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Nav pieejama neviena pārī savienota ierīce."</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Lai pievienotu vai atvienotu kādu ierīci, pieskarieties."</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Izmantot Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Savienojums izveidots"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio kopīgošana"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Pieskarieties, lai pārslēgtu vai kopīgotu audio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saglabāta"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"atvienot"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivizēt"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Atvērt iestatījumus"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Cita ierīce"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Pārskata pārslēgšana"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritātes režīmi"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gatavs"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Iestatījumi"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Ieslēgts"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Pakalpojums, kas nodrošina šo funkciju, iegūs piekļuvi visai informācijai, kas ierakstīšanas vai apraides laikā tiks rādīta jūsu ekrānā vai atskaņota jūsu ierīcē. Atļauja attiecas uz tādu informāciju kā paroles, maksājumu informācija, fotoattēli, ziņojumi un jūsu atskaņotais audio saturs."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Lietotnes kopīgošana vai ierakstīšana"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Vai kopīgot ekrānu ar lietotni <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Kopīgot vienu lietotni"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Kopīgot visu ekrānu"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Kopīgot vienu lietotni"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Kopīgot visu ekrānu"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kopīgojot visu ekrānu, lietotnei <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ir pieejams viss ekrāna saturs. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kopīgojot lietotni, lietotnei <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ir pieejams viss kopīgotajā lietotnē parādītais vai atskaņotais saturs. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Kopīgot ekrānu"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelīts, labs savienojums"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelīts, ir pieejams savienojums"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelīta SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Ārkārtas izsaukumi vai ārkārtas zvani"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Darba profils"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Jautri dažiem, bet ne visiem"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sistēmas saskarnes regulators sniedz papildu veidus, kā mainīt un pielāgot Android lietotāja saskarni. Nākamajās versijās šīs eksperimentālās funkcijas var tikt mainītas, bojātas vai to darbība var tikt pārtraukta. Turpinot esiet uzmanīgs."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Sakļaušanas ikona"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Izvēršanas ikona"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"vai"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Žests pāriešanai atpakaļ"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Žests pāriešanai uz sākumu"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Darbību taustiņš"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 7691ae6..1c853df 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> и други отворени апликации ја открија оваа слика од екранот."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Додај во белешка"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Опфати линк"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Снимач на екран"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Се обработува снимка од екран"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Тековно известување за сесија за снимање на екранот"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Штедач на екран"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Етернет"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Не вознемирувај"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Приоритетни режими"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Нема достапни спарени уреди"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Допрете за да воспоставите или да прекинете врска со уред"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Користи Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Поврзано"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Споделување аудио"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Допрете за да префрлите или споделите аудио"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Зачувано"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"прекини врска"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активирај"</string>
@@ -389,7 +392,7 @@
<string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Снимање екран"</string>
<string name="performance" msgid="6552785217174378320">"Изведба"</string>
<string name="user_interface" msgid="3712869377953950887">"Кориснички интерфејс"</string>
- <string name="thermal" msgid="6758074791325414831">"Термално"</string>
+ <string name="thermal" msgid="6758074791325414831">"Прегревање"</string>
<string name="custom" msgid="3337456985275158299">"Приспособено"</string>
<string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Приспособени поставки за следење"</string>
<string name="restore_default" msgid="5259420807486239755">"Врати на стандардно"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Отворете „Поставки“"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Друг уред"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Вклучи/исклучи преглед"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Приоритетни режими"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Поставки"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Вклучено"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Услугата што ја обезбедува функцијава ќе има пристап до сите податоци што се видливи на екранот или пуштени од вашиот уред додека се снима или емитува. Ова вклучува податоци како лозинките, деталите за плаќање, фотографиите, пораките и аудиото што го пуштате."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Споделете или снимете апликација"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Да се сподели вашиот екран со <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Споделете една апликација"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Споделете го целиот екран"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Споделете една апликација"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Споделете го целиот екран"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Додека го споделувате целиот екран, сè на екранот е видливо за <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Затоа, бидете внимателни со работи како лозинки, детали за плаќање, пораки, фотографии и аудио и видео."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Додека споделувате апликација, сѐ што се прикажува или пушта на таа апликација е видливо за <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Затоа, бидете внимателни со работи како лозинки, детали за плаќање, пораки, фотографии и аудио и видео."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Сподели екран"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Добра сателитска врска"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Достапна е сателитска врска"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Сателитски SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Итни повици или SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Работен профил"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Забава за некои, но не за сите"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Адаптерот на УИ на системот ви дава дополнителни начини за дотерување и приспособување на корисничкиот интерфејс на Android. Овие експериментални функции можеби ќе се изменат, расипат или ќе исчезнат во следните изданија. Продолжете со претпазливост."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Икона за собирање"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Икона за проширување"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"или"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Движење за назад"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Движење за почетен екран"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Копче за дејство"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 8c0378a..ef63d67 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> എന്ന ആപ്പും തുറന്നിരിക്കുന്ന മറ്റ് ആപ്പും ഈ സ്ക്രീൻഷോട്ട് തിരിച്ചറിഞ്ഞു."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"കുറിപ്പിലേക്ക് ചേർക്കുക"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"ലിങ്ക് ഉൾപ്പെടുത്തുക"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"സ്ക്രീൻ റെക്കോർഡർ"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"സ്ക്രീൻ റെക്കോർഡിംഗ് പ്രോസസുചെയ്യുന്നു"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ഒരു സ്ക്രീൻ റെക്കോർഡിംഗ് സെഷനായി നിലവിലുള്ള അറിയിപ്പ്"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"സ്ക്രീൻ സേവർ"</string>
<string name="ethernet_label" msgid="2203544727007463351">"ഇതർനെറ്റ്"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"ശല്യപ്പെടുത്തരുത്"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"മുൻഗണനാ മോഡുകൾ"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ജോടിയാക്കിയ ഉപകരണങ്ങളൊന്നും ലഭ്യമല്ല"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"ഒരു ഉപകരണം കണക്റ്റ് ചെയ്യാനോ വിച്ഛേദിക്കാനോ ടാപ്പ് ചെയ്യുക"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth ഉപയോഗിക്കുക"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"കണക്റ്റ് ചെയ്തു"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ഓഡിയോ പങ്കിടൽ"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ഓഡിയോ മാറാനോ പങ്കിടാനോ ടാപ്പ് ചെയ്യുക"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"സംരക്ഷിച്ചു"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"വിച്ഛേദിക്കുക"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"സജീവമാക്കുക"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"ക്രമീകരണം തുറക്കുക"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"മറ്റ് ഉപകരണം"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"അവലോകനം മാറ്റുക"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"മുൻഗണനാ മോഡുകൾ"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"ശരി"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ക്രമീകരണം"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"ഓണാണ്"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"റെക്കോർഡ് ചെയ്യുമ്പോഴോ കാസ്റ്റ് ചെയ്യുമ്പോഴോ നിങ്ങളുടെ ഉപകരണത്തിൽ നിന്ന് പ്ലേ ചെയ്യുന്നതോ നിങ്ങളുടെ സ്ക്രീനിൽ ദൃശ്യമാകുന്നതോ ആയ എല്ലാ വിവരങ്ങളിലേക്കും ഈ ഫംഗ്ഷൻ ലഭ്യമാക്കുന്ന സേവനത്തിന് ആക്സസ് ഉണ്ടായിരിക്കും. നിങ്ങൾ പ്ലേ ചെയ്യുന്ന ഓഡിയോ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, പാസ്വേഡുകൾ എന്നിവ പോലുള്ള വിവരങ്ങൾ ഇതിൽ ഉൾപ്പെടുന്നു."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"ഒരു ആപ്പ് പങ്കിടുക അല്ലെങ്കിൽ റെക്കോർഡ് ചെയ്യുക"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"നിങ്ങളുടെ സ്ക്രീൻ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതുമായി പങ്കിടണോ?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ഒരു ആപ്പ് പങ്കിടുക"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"സ്ക്രീൻ മുഴുവനായി പങ്കിടുക"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"ആപ്പ് പങ്കിടുക"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"സ്ക്രീൻ പൂർണമായും പങ്കിടുക"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"നിങ്ങളുടെ സ്ക്രീൻ മുഴുവനായി പങ്കിടുമ്പോൾ, സ്ക്രീനിലെ എല്ലാ കാര്യങ്ങളും <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതിന് ദൃശ്യമാകും. അതിനാൽ പാസ്വേഡുകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങളിൽ ശ്രദ്ധ പുലർത്തുക."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"നിങ്ങളുടെ ആപ്പ് പങ്കിടുമ്പോൾ, ആ ആപ്പിൽ കാണിക്കുന്നതോ പ്ലേ ചെയ്യുന്നതോ ആയ എല്ലാ കാര്യങ്ങളും <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> എന്നതിന് ദൃശ്യമാകും. അതിനാൽ പാസ്വേഡുകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങളിൽ ശ്രദ്ധ പുലർത്തുക."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"സ്ക്രീൻ പങ്കിടുക"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"സാറ്റലൈറ്റ്, മികച്ച കണക്ഷൻ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"സാറ്റലൈറ്റ്, കണക്ഷൻ ലഭ്യമാണ്"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"സാറ്റലൈറ്റ് SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"എമർജൻസി കോൾ അല്ലെങ്കിൽ SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ചിലർക്ക് വിനോദം, എന്നാൽ എല്ലാവർക്കുമില്ല"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Android ഉപയോക്തൃ ഇന്റർഫേസ് ആവശ്യമുള്ള രീതിയിൽ മാറ്റുന്നതിനും ഇഷ്ടാനുസൃതമാക്കുന്നതിനും സിസ്റ്റം UI ട്യൂണർ നിങ്ങൾക്ക് അധിക വഴികൾ നൽകുന്നു. ഭാവി റിലീസുകളിൽ ഈ പരീക്ഷണാത്മക ഫീച്ചറുകൾ മാറ്റുകയോ നിർത്തുകയോ അപ്രത്യക്ഷമാവുകയോ ചെയ്തേക്കാം. ശ്രദ്ധയോടെ മുന്നോട്ടുപോകുക."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ചുരുക്കൽ ഐക്കൺ"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"വികസിപ്പിക്കൽ ഐക്കൺ"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"അല്ലെങ്കിൽ"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"\'മടങ്ങുക\' ജെസ്ച്ചർ"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ഹോം ജെസ്ച്ചർ"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ആക്ഷൻ കീ"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index bfd48a4..ff8c52b 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> болон бусад нээлттэй апп энэ дэлгэцийн агшныг илрүүлсэн."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Тэмдэглэлд нэмэх"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Холбоосыг оруулах"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Дэлгэцийн үйлдэл бичигч"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Дэлгэц бичлэг боловсруулж байна"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Дэлгэц бичих горимын үргэлжилж буй мэдэгдэл"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Дэлгэц амраагч"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Этернет"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Бүү саад бол"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Чухал байдлаар нь ангилах горим"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Хослуулсан төхөөрөмж байхгүй"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Төхөөрөмжийг холбох эсвэл салгахын тулд товшино уу"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth-г ашиглах"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Холбогдсон"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Аудио хуваалцах"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Аудиог сэлгэх эсвэл хуваалцахын тулд товшино уу"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Хадгалсан"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"салгах"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"идэвхжүүлэх"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Тохиргоог нээх"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Бусад төхөөрөмж"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Тоймыг асаах/унтраах"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Чухал байдлаар нь ангилах горим"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Болсон"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Тохиргоо"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Асаалттай"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Энэ функцийг олгож буй үйлчилгээ нь бичлэг хийж эсвэл дамжуулж байх үед таны дэлгэцэд харуулсан эсвэл төхөөрөмжөөс тань тоглуулсан бүх мэдээлэлд хандах эрхтэй. Үүнд нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг болон таны тоглуулдаг аудио зэрэг мэдээлэл багтана."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Апп хуваалцах эсвэл бичих"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Дэлгэцээ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-тай хуваалцах уу?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Нэг апп хуваалцах"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Дэлгэцийг бүтнээр нь хуваалцах"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Нэг апп хуваалцах"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Дэлгэцийг бүтнээр нь хуваалцах"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Таныг дэлгэцээ бүхэлд нь хуваалцаж байхад дэлгэц дээр тань байгаа аливаа зүйл <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-д харагдана. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг, аудио, видео зэрэг зүйлд болгоомжтой хандаарай."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Таныг апп хуваалцаж байхад тухайн аппад харуулж эсвэл тоглуулж буй аливаа зүйл <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>-д харагдана. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг, аудио, видео зэрэг зүйлд болгоомжтой хандаарай."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Дэлгэцийг хуваалцах"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Хиймэл дагуул, холболт сайн байна"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Хиймэл дагуул, холболт боломжтой"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Хиймэл дагуул SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Яаралтай дуудлага эсвэл SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Ажлын профайл"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Зарим хүнд хөгжилтэй байж болох ч бүх хүнд тийм биш"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Системийн UI Tохируулагч нь Android хэрэглэгчийн интерфэйсийг тааруулах, өөрчлөх нэмэлт аргыг зааж өгөх болно. Эдгээр туршилтын тохиргоо нь цаашид өөрчлөгдөх, эвдрэх, алга болох магадлалтай. Үйлдлийг болгоомжтой хийнэ үү."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Хураах дүрс тэмдэг"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Дэлгэх дүрс тэмдэг"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"эсвэл"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Буцах зангаа"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Үндсэн нүүрний зангаа"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Тусгай товчлуур"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index d124ce3..76515d2 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> आणि उघडलेल्या इतर अॅप्सनी हा स्क्रीनशॉट डिटेक्ट केला."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"टीप जोडा"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"लिंकचा समावेश करा"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"स्क्रीन रेकॉर्डर"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रीन रेकॉर्डिंग प्रोसेस सुरू"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"स्क्रीन रेकॉर्ड सत्रासाठी सुरू असलेली सूचना"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"स्क्रीन सेव्हर"</string>
<string name="ethernet_label" msgid="2203544727007463351">"इथरनेट"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"व्यत्यय आणू नका"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"प्राधान्य मोड"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ब्लूटूथ"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"कोणतेही जोडलेले डिव्हाइसेस उपलब्ध नाहीत"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"डिव्हाइस कनेक्ट किंवा डिस्कनेक्ट करण्यासाठी टॅप करा"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ब्लूटूथ वापरा"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"कनेक्ट केले"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ऑडिओ शेअरिंग"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"व्हिडिओवर स्विच करण्यासाठी टॅप करा किंवा शेअर करा"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"सेव्ह केले"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"डिस्कनेक्ट करा"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ॲक्टिव्हेट करा"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"सेटिंग्ज उघडा"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"इतर डिव्हाइस"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"अवलोकन टॉगल करा."</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"प्राधान्य मोड"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"पूर्ण झाले"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"सेटिंग्ज"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"सुरू आहे"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"रेकॉर्ड किंवा कास्ट करत असताना, हे कार्य पुरवणाऱ्या सेवेला तुमच्या स्क्रीनवर दाखवलेल्या किंवा डिव्हाइसवर प्ले केलेल्या सर्व माहितीचा अॅक्सेस असेल. यामध्ये पासवर्ड, पेमेंट तपशील, फोटो, मेसेज आणि तुम्ही प्ले करत असलेला ऑडिओ यासारख्या माहितीचा समावेश आहे."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"अॅप शेअर किंवा रेकॉर्ड करा"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"तुमची स्क्रीन <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> सह शेअर करायची आहे का?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"एक अॅप शेअर करा"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"संपूर्ण स्क्रीन शेअर करा"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"एक अॅप शेअर करा"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"संपूर्ण स्क्रीन शेअर करा"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"तुम्ही तुमची संपूर्ण स्क्रीन कास्ट करता, तेव्हा तुमच्या स्क्रीनवरील कोणत्याही गोष्टी <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> साठी दृश्यमान असतात. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"तुम्ही अॅप शेअर करता, तेव्हा त्या अॅपमध्ये दाखवल्या किंवा प्ले होणाऱ्या कोणत्याही गोष्टी <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> साठी दृश्यमान असतात. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"स्क्रीन शेअर करा"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"सॅटेलाइट, चांगले कनेक्शन"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"सॅटेलाइट, कनेक्शन उपलब्ध"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"सॅटेलाइट SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"आणीबाणी कॉल किंवा SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"कार्य प्रोफाईल"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"सर्वांसाठी नाही तर काहींसाठी मजेदार असू शकते"</string>
<string name="tuner_warning" msgid="1861736288458481650">"सिस्टम UI ट्युनर आपल्याला Android यूझर इंटरफेस ट्विक आणि कस्टमाइझ करण्याचे अनेक प्रकार देते. ही प्रयोगात्मक वैशिष्ट्ये बदलू शकतात, खंडित होऊ शकतात किंवा भविष्यातील रिलीज मध्ये कदाचित दिसणार नाहीत. सावधगिरी बाळगून पुढे सुरू ठेवा."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"कोलॅप्स करा आयकन"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"विस्तार करा आयकन"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"किंवा"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"मागे जा जेश्चर"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"होम जेश्चर"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"अॅक्शन की"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 8385682..181b0c7 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> dan apl lain yang dibuka telah mengesan tangkapan skrin ini."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Tambahkan pada nota"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Sertakan pautan"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Perakam Skrin"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Memproses rakaman skrin"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Pemberitahuan breterusan untuk sesi rakaman skrin"</string>
@@ -291,7 +292,7 @@
<string name="start_dreams" msgid="9131802557946276718">"Penyelamat skrin"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Jangan Ganggu"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Mod keutamaan"</string>
+ <string name="quick_settings_modes_label" msgid="879156359479504244">"Mod"</string>
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Tiada peranti berpasangan tersedia"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Ketik untuk menyambungkan atau memutuskan sambungan peranti"</string>
@@ -300,6 +301,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Gunakan Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Disambungkan"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Perkongsian Audio"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Ketik untuk menukar atau berkongsi audio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Disimpan"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"putuskan sambungan"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktifkan"</string>
@@ -431,7 +433,7 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Buka Tetapan"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Peranti lain"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Togol Ikhtisar"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Mod keutamaan"</string>
+ <string name="zen_modes_dialog_title" msgid="8854640808100096934">"Mod"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Selesai"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Tetapan"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Hidup"</string>
@@ -532,8 +534,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Perkhidmatan yang menyediakan fungsi ini boleh mengakses semua maklumat yang boleh dilihat pada skrin anda atau dimainkan daripada peranti anda semasa membuat rakaman atau penghantaran. Maklumat ini termasuk kata laluan, butiran pembayaran, foto, mesej dan audio yang anda mainkan."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Kongsi atau rakam apl"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Kongsi skrin anda dengan <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Kongsi satu apl"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Kongsi seluruh skrin"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Kongsi satu apl"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Kongsi seluruh skrin"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Apabila anda berkongsi seluruh skrin anda, apa-apa sahaja kandungan pada skrin anda boleh dilihat oleh <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Oleh hal yang demikian, berhati-hati dengan perkara seperti kata laluan, butiran pembayaran, mesej, foto dan audio serta video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Apabila anda berkongsi apl, apa-apa sahaja kandungan yang dipaparkan atau dimainkan pada apl boleh dilihat oleh <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Oleh hal yang demikian, berhati-hati dengan perkara seperti kata laluan, butiran pembayaran, mesej, foto dan audio serta video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Kongsi skrin"</string>
@@ -718,8 +724,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, sambungan yang baik"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, sambungan tersedia"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via Satelit"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Panggilan kecemasan atau SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil kerja"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Menarik untuk sesetengah orang tetapi bukan untuk semua"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Penala UI Sistem memberi anda cara tambahan untuk mengolah dan menyesuaikan antara muka Android. Ciri eksperimen ini boleh berubah, rosak atau hilang dalam keluaran masa hadapan. Teruskan dengan berhati-hati."</string>
@@ -1386,6 +1391,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Kuncupkan ikon"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Kembangkan ikon"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"atau"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gerak isyarat kembali"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gerak isyarat pergi ke laman utama"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Kekunci tindakan"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 60c74c1..afc57ac 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> နှင့် အခြားဖွင့်ထားသော အက်ပ်များက ဤဖန်သားပြင်ဓာတ်ပုံကို တွေ့ရှိသည်။"</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"မှတ်စုတွင် ထည့်ရန်"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"လင့်ခ်ထည့်သွင်းရန်"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"ဖန်သားပြင်ရိုက်ကူးစက်"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"စကရင်ရိုက်ကူးမှု အပြီးသတ်နေသည်"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ဖန်သားပြင် ရိုက်ကူးသည့် စက်ရှင်အတွက် ဆက်တိုက်လာနေသော အကြောင်းကြားချက်"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"စခရင်နားချိန်ပုံ"</string>
<string name="ethernet_label" msgid="2203544727007463351">"အီသာနက်"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"မနှောင့်ယှက်ရ"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"ဦးစားပေးမုဒ်"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ဘလူးတုသ်"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ချိတ်တွဲထားသည့် ကိရိယာများ မရှိ"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"စက်ကို ချိတ်ဆက်ရန် (သို့) ချိတ်ဆက်မှုဖြုတ်ရန် တို့ပါ"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ဘလူးတုသ်သုံးရန်"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ချိတ်ဆက်ထားသည်"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"အော်ဒီယို မျှဝေခြင်း"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"အသံ ပြောင်းရန်/မျှဝေရန် တို့ပါ"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"သိမ်းထားသည်"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ချိတ်ဆက်မှုဖြုတ်ရန်"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"စသုံးရန်"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"ဆက်တင်များဖွင့်ရန်"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"အခြားစက်ပစ္စည်း"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ဖွင့်၊ ပိတ် အနှစ်ချုပ်"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ဦးစားပေးမုဒ်"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"ပြီးပြီ"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ဆက်တင်များ"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"ဖွင့်"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ဤလုပ်ဆောင်ချက်ကို ပေးအပ်သည့် ဝန်ဆောင်မှုသည် ရုပ်သံဖမ်းနေစဉ် (သို့) ကာစ်လုပ်နေစဉ် သင့်မျက်နှာပြင်တွင် မြင်ရသော (သို့) သင့်စက်တွင် ဖွင့်ထားသော အချက်အလက်မှန်သမျှကို သုံးနိုင်ပါမည်။ ၎င်းတွင် စကားဝှက်များ၊ ငွေပေးချေမှုအသေးစိတ်များ၊ ဓာတ်ပုံများ၊ မက်ဆေ့ဂျ်များနှင့် သင်ဖွင့်သည့်အသံကဲ့သို့သော အချက်အလက်များ ပါဝင်သည်။"</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"အက်ပ် မျှဝေခြင်း (သို့) ရိုက်ကူးခြင်း"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"သင့်စခရင်ကို <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> နှင့် မျှဝေမလား။"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"အက်ပ်တစ်ခု မျှဝေရန်"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"စခရင်တစ်ခုလုံး မျှဝေရန်"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"အက်ပ်တစ်ခု မျှဝေရန်"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"စခရင်တစ်ခုလုံး မျှဝေရန်"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"သင့်စခရင်တစ်ခုလုံးကို မျှဝေနေချိန်တွင် စခရင်ပေါ်ရှိ အရာအားလုံးကို <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> က မြင်နိုင်သည်။ စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"အက်ပ်ကို မျှဝေနေချိန်တွင် ယင်းအက်ပ်တွင် ပြထားသော (သို့) ဖွင့်ထားသော အရာအားလုံးကို <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> က မြင်နိုင်သည်။ စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"စခရင် မျှဝေရန်"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ဂြိုဟ်တု၊ ချိတ်ဆက်မှု ကောင်းသည်"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ဂြိုဟ်တု၊ ချိတ်ဆက်မှု ရနိုင်သည်"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"အရေးပေါ်ဖုန်းခေါ်ခြင်း (သို့) SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"အလုပ် ပရိုဖိုင်"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"အချို့သူများ အတွက် ပျော်စရာ ဖြစ်ပေမဲ့ အားလုံး အတွက် မဟုတ်ပါ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"စနစ် UI Tuner က သင့်အတွက် Android အသုံးပြုသူ အင်တာဖေ့စ်ကို ပြောင်းရန်နှင့် စိတ်ကြိုက်ပြုလုပ်ရန် နည်းလမ်း အပိုများကို သင့်အတွက် စီစဉ်ပေးသည်။ အနာဂတ်ဗားရှင်းများတွင် ဤစမ်းသပ်အင်္ဂါရပ်များမှာ ပြောင်းလဲ၊ ပျက်စီး သို့မဟုတ် ပျောက်ကွယ်သွားနိုင်သည်။ သတိဖြင့် ရှေ့ဆက်ပါ။"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"လျှော့ပြရန် သင်္ကေတ"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ပိုပြရန် သင်္ကေတ"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"သို့မဟုတ်"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"နောက်သို့ လက်ဟန်"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ပင်မစာမျက်နှာ လက်ဟန်"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"လုပ်ဆောင်ချက်ကီး"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 72ccd2c..d222f31 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> og andre åpne apper har registrert dette skjermbildet."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Legg til i notat"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Inkluder linken"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Skjermopptak"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandler skjermopptaket"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Vedvarende varsel for et skjermopptak"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Skjermsparer"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ikke forstyrr"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioritetsmoduser"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Ingen sammenkoblede enheter er tilgjengelige"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Trykk for å koble en enhet til eller fra"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bruk Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Tilkoblet"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Lyddeling"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Trykk for å bytte eller dele lyd"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Lagret"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"koble fra"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiver"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Åpne Innstillinger"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Annen enhet"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Slå oversikten av eller på"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioritetsmoduser"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Ferdig"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Innstillinger"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"På"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Tjenesten som leverer denne funksjonen, får tilgang til all informasjon som vises på skjermen eller spilles av fra enheten mens du tar opp eller caster noe. Dette inkluderer informasjon som passord, betalingsopplysninger, bilder, meldinger og lyd du spiller av."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Del eller ta opp en app"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Vil du dele skjermen med <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Del én app"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Del hele skjermen"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Del én app"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Del hele skjermen"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Når du deler hele skjermen, er alt på skjermen synlig for <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Når du deler en app, er alt som vises eller spilles av i appen, synlig for <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Del skjermen"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellitt – god tilkobling"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellitt – tilkobling tilgjengelig"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS-alarm via satellitt"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Nødanrop eller SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work-profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Gøy for noen – ikke for alle"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Med System UI Tuner har du flere måter å justere og tilpasse Android-brukergrensesnittet på. Disse eksperimentelle funksjonene kan endres, avbrytes eller fjernes i fremtidige utgivelser. Fortsett med forbehold."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Skjul-ikon"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Vis-ikon"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"eller"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Tilbakebevegelse"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Startskjermbevegelse"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Handlingstast"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index d680645..8af52a1 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> र खुला रहेका अन्य एपहरूले यो स्क्रिनसट भेट्टाएका छन्।"</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"नोटमा सेभ गर्नुहोस्"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"लिंक समावेश गर्नुहोस्"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"स्क्रिन रेकर्डर"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"स्क्रिन रेकर्डिङको प्रक्रिया अघि बढाइँदै"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"कुनै स्क्रिन रेकर्ड गर्ने सत्रका लागि चलिरहेको सूचना"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"स्क्रिन सेभर"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"बाधा नपुऱ्याउनुहोस्"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"महत्त्वपूर्ण मोडहरू"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ब्लुटुथ"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"जोडी उपकरणहरू उपलब्ध छैन"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"कुनै डिभाइस कनेक्ट गर्न वा डिस्कनेक्ट गर्न ट्याप गर्नुहोस्"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ब्लुटुथ प्रयोग गर्नुहोस्"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"कनेक्ट गरिएको छ"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"अडियो सेयरिङ"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"अडियो बदल्न वा सेयर गर्न ट्याप गर्नुहोस्"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"सेभ गरिएको छ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"डिस्कनेक्ट गर्नुहोस्"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"एक्टिभेट गर्नुहोस्"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"सेटिङ खोल्नुहोस्"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"अर्को डिभाइड"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"परिदृश्य टगल गर्नुहोस्"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"महत्त्वपूर्ण मोडहरू"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"सम्पन्न भयो"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"सेटिङ"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"अन छ"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"यो फङ्सन प्रदान गर्ने सेवाले रेकर्ड वा कास्ट गर्दै गर्दा तपाईंको स्क्रिनमा देखिने सबै जानकारी अथवा तपाईंको डिभाइसबाट प्ले गरिने सबै सामग्री हेर्न तथा प्रयोग गर्न सक्छ। यसअन्तर्गत पासवर्ड, भुक्तानीसम्बन्धी विवरण, फोटो, म्यासेज र तपाईंले प्ले गर्ने अडियो जस्ता कुराहरू समावेश हुन्छन्।"</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"कुनै एप सेयर वा रेकर्ड गर्नुहोस्"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"स्क्रिन <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> सँग सेयर गर्ने हो?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"एउटा एप सेयर गर्नुहोस्"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"पूरै स्क्रिन सेयर गर्नुहोस्"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"एउटा एप सेयर गर्नुहोस्"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"पूरै स्क्रिन सेयर गर्नुहोस्"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"तपाईंले पूरै स्क्रिन सेयर गरिरहेका बेला तपाईंको स्क्रिनमा देखिने सबै सामग्री <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> मा देखिन्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"तपाईंले यो एप सेयर गरिरहेका बेला यो एपमा देखाइने वा प्ले गरिने सबै सामग्री <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> मा देखिन्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"स्क्रिन सेयर गर्नुहोस्"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"स्याटलाइट, राम्रो कनेक्सन"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"स्याटलाइट, कनेक्सन उपलब्ध छ"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"स्याटलाइट SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"आपत्कालीन कल वा SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"कार्य प्रोफाइल"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"केहीका लागि रमाइलो हुन्छ तर सबैका लागि होइन"</string>
<string name="tuner_warning" msgid="1861736288458481650">"सिस्टम UI ट्युनरले तपाईँलाई Android प्रयोगकर्ता इन्टरफेस कस्टम गर्न र ट्विक गर्न थप तरिकाहरू प्रदान गर्छ। यी प्रयोगात्मक सुविधाहरू भावी विमोचनमा परिवर्तन हुन, बिग्रिन वा हराउन सक्ने छन्। सावधानीपूर्वक अगाडि बढ्नुहोस्।"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"\"कोल्याप्स गर्नुहोस्\" आइकन"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"\"एक्स्पान्ड गर्नुहोस्\" आइकन"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"वा"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ब्याक जेस्चर"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"होम जेस्चर"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"एक्सन की"</string>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index 21f1cfb..c1eff5f 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -16,7 +16,11 @@
NOTE: You might also want to edit: core/res/res/values-night/*.xml
-->
-<resources>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <!-- The dark background color behind the shade -->
+ <color name="shade_scrim_background_dark">@androidprv:color/system_under_surface_dark</color>
+
<!-- The color of the legacy notifications with customs backgrounds (gingerbread and lollipop.)
It's fine to override this color since at that point the shade was dark. -->
<color name="notification_legacy_background_color">@color/GM2_grey_900</color>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 6a675b8..24a4835 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> en andere geopende apps hebben dit screenshot waargenomen."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Toevoegen aan notitie"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Link opnemen"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Schermopname"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Schermopname verwerken"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Doorlopende melding voor een schermopname-sessie"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Screensaver"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Niet storen"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioriteitsmodi"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Geen gekoppelde apparaten beschikbaar"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tik om een apparaat te verbinden of de verbinding te verbreken"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth gebruiken"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Verbonden"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio delen"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tik om audio te schakelen of te delen"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Opgeslagen"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"loskoppelen"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activeren"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Instellingen openen"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Ander apparaat"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Overzicht aan- of uitzetten"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriteitsmodi"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Klaar"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Instellingen"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Aan"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"De service die deze functie levert, krijgt tijdens het opnemen of casten toegang tot alle informatie die zichtbaar is op je scherm of wordt afgespeeld op je apparaat. Dit omvat informatie zoals wachtwoorden, betalingsgegevens, foto\'s, berichten en audio die je afspeelt."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"App delen of opnemen"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Je scherm delen met <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Eén app delen"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Hele scherm delen"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Eén app delen"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Hele scherm delen"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Als je het hele scherm deelt, is alles op je scherm zichtbaar voor <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Als je een app deelt, is alles dat wordt getoond of afgespeeld in die app zichtbaar voor <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Scherm delen"</string>
@@ -629,7 +637,7 @@
<string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Instellingen"</string>
<string name="volume_panel_captioning_title" msgid="5984936949147684357">"Live ondertiteling"</string>
<string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume verlaagd naar een veiliger niveau"</string>
- <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Het hoofdtelefoonvolume is langer dan de aanbevolen tijd hoog geweest"</string>
+ <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Het koptelefoonvolume is langer dan de aanbevolen tijd hoog geweest"</string>
<string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Het hoofdtelefoonvolume overschrijdt de veiligheidslimiet voor deze week"</string>
<string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Blijven luisteren"</string>
<string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Volume omlaag"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliet, goede verbinding"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliet, verbinding beschikbaar"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via satelliet"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Noodoproepen of SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Werkprofiel"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Leuk voor sommige gebruikers, maar niet voor iedereen"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Met Systeem-UI-tuner beschikt u over extra manieren om de Android-gebruikersinterface aan te passen. Deze experimentele functies kunnen veranderen, vastlopen of verdwijnen in toekomstige releases. Ga voorzichtig verder."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icoon voor samenvouwen"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Icoon voor uitvouwen"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"of"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gebaar voor terug"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gebaar voor startscherm"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Actietoets"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 6e63643..67537c2 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ଏବଂ ଅନ୍ୟ ଓପନ ଆପ୍ସ ଏହି ସ୍କ୍ରିନସଟକୁ ଚିହ୍ନଟ କରିଛି।"</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"ନୋଟରେ ଯୋଗ କରନ୍ତୁ"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"ଲିଙ୍କକୁ ଅନ୍ତର୍ଭୁକ୍ତ କରନ୍ତୁ"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"ସ୍କ୍ରିନ ରେକର୍ଡର"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ସ୍କ୍ରିନ ରେକର୍ଡିଂର ପ୍ରକ୍ରିୟାକରଣ"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ଏକ ସ୍କ୍ରିନ୍ ରେକର୍ଡ୍ ସେସନ୍ ପାଇଁ ଚାଲୁଥିବା ବିଜ୍ଞପ୍ତି"</string>
@@ -228,7 +229,7 @@
<string name="face_re_enroll_dialog_title" msgid="6392173708176069994">"ଫେସ ଅନଲକ ସେଟ ଅପ କରନ୍ତୁ"</string>
<string name="face_re_enroll_dialog_content" msgid="7353502359464038511">"ଫେସ ଅନଲକ ପୁଣି ସେଟ ଅପ କରିବାକୁ ଆପଣଙ୍କ ବର୍ତ୍ତମାନର ଫେସ ମଡେଲ ଡିଲିଟ ହୋଇଯିବ।\n\nଆପଣଙ୍କ ଫୋନକୁ ଅନଲକ କରିବା ପାଇଁ ଆପଣଙ୍କ ଫେସ ବ୍ୟବହାର କରିବାକୁ ଆପଣଙ୍କୁ ଏହି ଫିଚର ପୁଣି ସେଟ ଅପ କରିବାକୁ ହେବ।"</string>
<string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"ଫେସ ଅନଲକ ସେଟ ଅପ କରାଯାଇପାରିଲା ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରିବା ପାଇଁ ସେଟିଂସକୁ ଯାଆନ୍ତୁ।"</string>
- <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ଟିପଚିହ୍ନ ସେନସର୍କୁ ଛୁଅଁନ୍ତୁ"</string>
+ <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ଟିପଚିହ୍ନ ସେନସରକୁ ସ୍ପର୍ଶ କରନ୍ତୁ"</string>
<string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"ଜାରି ରଖିବାକୁ ଅନଲକ ଆଇକନ ଦବାନ୍ତୁ"</string>
<string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"ଫେସ ଚିହ୍ନଟ କରାଯାଇନାହିଁ। ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
<!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) -->
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"ସ୍କ୍ରିନ୍ ସେଭର୍"</string>
<string name="ethernet_label" msgid="2203544727007463351">"ଇଥରନେଟ୍"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"ପ୍ରାଥମିକତା ମୋଡ"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ବ୍ଲୁଟୁଥ"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ପେୟାର୍ ହୋଇଥିବା କୌଣସି ଡିଭାଇସ୍ ଉପଲବ୍ଧ ନାହିଁ"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"ଏକ ଡିଭାଇସ କନେକ୍ଟ କିମ୍ବା ଡିସକନେକ୍ଟ କରିବାକୁ ଟାପ କରନ୍ତୁ"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ବ୍ଲୁଟୁଥ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"କନେକ୍ଟ କରାଯାଇଛି"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ଅଡିଓ ସେୟାରିଂ"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ଅଡିଓ ସୁଇଚ କିମ୍ବା ସେୟାର କରିବାକୁ ଟାପ କରନ୍ତୁ"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ସେଭ କରାଯାଇଛି"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ଡିସକନେକ୍ଟ କରନ୍ତୁ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ଚାଲୁ କରନ୍ତୁ"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"ସେଟିଂସ ଖୋଲନ୍ତୁ"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"ଅନ୍ୟ ଡିଭାଇସ୍"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ସଂକ୍ଷିପ୍ତ ବିବରଣୀକୁ ଟୋଗଲ୍ କରନ୍ତୁ"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ପ୍ରାଥମିକତା ମୋଡ"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"ହୋଇଗଲା"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ସେଟିଂସ"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"ଚାଲୁ ଅଛି"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ରେକର୍ଡ ବା କାଷ୍ଟ କରିବା ସମୟରେ ଆପଣଙ୍କ ଡିଭାଇସରୁ ପ୍ଲେ ହେଉଥିବା କିମ୍ବା ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ଦେଖାଯାଉଥିବା ସମସ୍ତ ସୂଚନାକୁ ଏହି ଫଙ୍କସନ ପ୍ରଦାନ କରୁଥିବା ସେବାର ଆକ୍ସେସ ରହିବ। ଏଥିରେ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ଫଟୋ, ମେସେଜ ଏବଂ ଆପଣ ପ୍ଲେ କରୁଥିବା ଅଡିଓ ପରି ସୂଚନା ଅନ୍ତର୍ଭୁକ୍ତ ଅଛି।"</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"ଏକ ଆପକୁ ସେୟାର କିମ୍ବା ରେକର୍ଡ କରନ୍ତୁ"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ସହ ଆପଣଙ୍କ ସ୍କ୍ରିନକୁ ସେୟାର କରନ୍ତୁ?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ଗୋଟିଏ ଆପ ସେୟାର କରନ୍ତୁ"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନ ସେୟାର କରନ୍ତୁ"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"ଗୋଟିଏ ଆପ ସେୟାର କରନ୍ତୁ"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନ ସେୟାର କରନ୍ତୁ"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"ଆପଣ ଆପଣଙ୍କ ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନକୁ ସେୟାର କରିବା ସମୟରେ ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ସବୁକିଛି <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>କୁ ଦେଖାଯାଏ। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"ଆପଣ ଏକ ଆପ ସେୟାର କରିବା ସମୟରେ, ସେହି ଆପରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ପ୍ଲେ ହେଉଥିବା ସବୁକିଛି <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>କୁ ଦେଖାଯାଏ। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"ସ୍କ୍ରିନ ସେୟାର କରନ୍ତୁ"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ସାଟେଲାଇଟ, ଭଲ କନେକ୍ସନ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ସାଟେଲାଇଟ, କନେକ୍ସନ ଉପଲବ୍ଧ"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"ସେଟେଲାଇଟ SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ଜରୁରୀକାଳୀନ କଲ କିମ୍ବା SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ୱର୍କ ପ୍ରୋଫାଇଲ୍"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"କେତେକଙ୍କ ପାଇଁ ମଜାଦାର, କିନ୍ତୁ ସମସ୍ତଙ୍କ ପାଇଁ ନୁହେଁ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Android ୟୁଜର୍ ଇଣ୍ଟରଫେସ୍ ବଦଳାଇବାକୁ ତଥା ନିଜ ପସନ୍ଦ ଅନୁଯାୟୀ କରିବାକୁ ସିଷ୍ଟମ୍ UI ଟ୍ୟୁନର୍ ଆପଣଙ୍କୁ ଅତିରିକ୍ତ ଉପାୟ ପ୍ରଦାନ କରେ। ଏହି ପରୀକ୍ଷାମୂଳକ ସୁବିଧାମାନ ବଦଳିପାରେ, ଭାଙ୍ଗିପାରେ କିମ୍ବା ଭବିଷ୍ୟତର ରିଲିଜ୍ଗୁଡ଼ିକରେ ନଦେଖାଯାଇପାରେ। ସତର୍କତାର ସହ ଆଗକୁ ବଢ଼ନ୍ତୁ।"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ଆଇକନକୁ ସଙ୍କୁଚିତ କରନ୍ତୁ"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ଆଇକନକୁ ବିସ୍ତାର କରନ୍ତୁ"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"କିମ୍ବା"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ବେକ ଜେଶ୍ଚର"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ହୋମ ଜେଶ୍ଚର"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ଆକ୍ସନ କୀ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index cd7790f..1927d45 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -104,13 +104,14 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ਅਤੇ ਹੋਰ ਖੁੱਲ੍ਹੀਆਂ ਐਪਾਂ ਨੂੰ ਇਸ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦਾ ਪਤਾ ਲੱਗਿਆ ਹੈ।"</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"ਨੋਟ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"ਲਿੰਕ ਸ਼ਾਮਲ ਕਰੋ"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਰ"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਜਾਰੀ ਹੈ"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"ਕਿਸੇ ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ ਸੈਸ਼ਨ ਲਈ ਚੱਲ ਰਹੀ ਸੂਚਨਾ"</string>
<string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"ਕੀ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ ਨੂੰ ਰਿਕਾਰਡ ਕਰਨਾ ਹੈ?"</string>
<string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"ਇੱਕ ਐਪ ਨੂੰ ਰਿਕਾਰਡ ਕਰੋ"</string>
<string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="2794896384693120020">"ਪੂਰੀ ਸਕ੍ਰੀਨ ਨੂੰ ਰਿਕਾਰਡ ਕਰੋ"</string>
- <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"ਜਦੋਂ ਤੁਸੀਂ ਆਪਣੀ ਪੂਰੀ ਸਕ੍ਰੀਨ ਨੂੰ ਰਿਕਾਰਡ ਕਰ ਰਹੇ ਹੁੰਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖਾਈ ਜਾ ਰਹੀ ਹਰ ਚੀਜ਼ ਨੂੰ ਰਿਕਾਰਡ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string>
+ <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"ਜਦੋਂ ਤੁਸੀਂ ਆਪਣੀ ਪੂਰੀ ਸਕ੍ਰੀਨ ਨੂੰ ਰਿਕਾਰਡ ਕਰ ਰਹੇ ਹੁੰਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖਾਈ ਜਾ ਰਹੀ ਹਰ ਚੀਜ਼ ਨੂੰ ਰਿਕਾਰਡ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਨਾਲ ਹੀ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string>
<string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"ਜਦੋਂ ਤੁਸੀਂ ਕਿਸੇ ਐਪ ਨੂੰ ਰਿਕਾਰਡ ਕਰ ਰਹੇ ਹੁੰਦੇ ਹੋ, ਤਾਂ ਉਸ ਐਪ ਵਿੱਚ ਦਿਖਾਈ ਜਾਂ ਚਲਾਈ ਜਾ ਰਹੀ ਹਰ ਚੀਜ਼ ਨੂੰ ਰਿਕਾਰਡ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string>
<string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ ਕਰੋ"</string>
<string name="screenrecord_app_selector_title" msgid="3854492366333954736">"ਰਿਕਾਰਡ ਕਰਨ ਲਈ ਐਪ ਚੁਣੋ"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"ਸਕ੍ਰੀਨ ਸੇਵਰ"</string>
<string name="ethernet_label" msgid="2203544727007463351">"ਈਥਰਨੈਟ"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"ਤਰਜੀਹ ਮੋਡ"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"ਬਲੂਟੁੱਥ"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ਕੋਈ ਜੋੜਾਬੱਧ ਕੀਤੀਆਂ ਡੀਵਾਈਸਾਂ ਉਪਲਬਧ ਨਹੀਂ"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"ਡੀਵਾਈਸ ਨੂੰ ਕਨੈਕਟ ਜਾਂ ਡਿਸਕਨੈਕਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ਬਲੂਟੁੱਥ ਵਰਤੋ"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ਕਨੈਕਟ ਹੈ"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ਆਡੀਓ ਸਾਂਝਾਕਰਨ"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ਆਡੀਓ ਨੂੰ ਸਵਿੱਚ ਜਾਂ ਸਾਂਝਾ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ਡਿਸਕਨੈਕਟ ਕਰੋ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ਕਿਰਿਆਸ਼ੀਲ ਕਰੋ"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹੋ"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"ਹੋਰ ਡੀਵਾਈਸ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ਰੂਪ-ਰੇਖਾ ਨੂੰ ਟੌਗਲ ਕਰੋ"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ਤਰਜੀਹ ਮੋਡ"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"ਹੋ ਗਿਆ"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ਸੈਟਿੰਗਾਂ"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"ਚਾਲੂ"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ਇਸ ਫੰਕਸ਼ਨ ਦੇ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਕੋਲ ਬਾਕੀ ਸਾਰੀ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ ਜੋ ਕਿ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖਣਯੋਗ ਹੁੰਦੀ ਹੈ ਜਾਂ ਰਿਕਾਰਡਿੰਗ ਜਾਂ ਕਾਸਟ ਕਰਨ ਵੇਲੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਚਲਾਈ ਜਾਂਦੀ ਹੈ। ਇਸ ਵਿੱਚ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਫ਼ੋਟੋਆਂ, ਸੁਨੇਹਿਆਂ ਅਤੇ ਤੁਹਾਡੇ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਆਡੀਓ ਦੀ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਹੈ।"</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"ਐਪ ਨੂੰ ਸਾਂਝਾ ਕਰੋ ਜਾਂ ਰਿਕਾਰਡ ਕਰੋ"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"ਕੀ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਨਾਲ ਆਪਣੀ ਸਕ੍ਰੀਨ ਸਾਂਝੀ ਕਰਨੀ ਹੈ?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ਇੱਕ ਐਪ ਸਾਂਝੀ ਕਰੋ"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"ਪੂਰੀ ਸਕ੍ਰੀਨ ਸਾਂਝੀ ਕਰੋ"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"ਇੱਕ ਐਪ ਸਾਂਝੀ ਕਰੋ"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"ਪੂਰੀ ਸਕ੍ਰੀਨ ਸਾਂਝੀ ਕਰੋ"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"ਪੂਰੀ ਸਕ੍ਰੀਨ ਨੂੰ ਸਾਂਝਾ ਕਰਨ ਦੌਰਾਨ, ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖ ਰਹੀ ਹਰੇਕ ਚੀਜ਼ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> \'ਤੇ ਵੀ ਦਿਖਣਯੋਗ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"ਕਿਸੇ ਐਪ ਨੂੰ ਸਾਂਝਾ ਕਰਨ ਦੌਰਾਨ, ਉਸ ਐਪ \'ਤੇ ਦਿਖ ਰਹੀ ਜਾਂ ਚਲਾਈ ਗਈ ਹਰੇਕ ਚੀਜ਼ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ਨੂੰ ਦਿਖਣਯੋਗ ਹੁੰਦੀ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"ਸਕ੍ਰੀਨ ਸਾਂਝੀ ਕਰੋ"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ਸੈਟੇਲਾਈਟ, ਕਨੈਕਸ਼ਨ ਵਧੀਆ ਹੈ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ਸੈਟੇਲਾਈਟ, ਕਨੈਕਸ਼ਨ ਉਪਲਬਧ ਹੈ"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"ਸੈਟੇਲਾਈਟ SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ਐਮਰਜੈਂਸੀ ਕਾਲਾਂ ਜਾਂ ਸਹਾਇਤਾ"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ਕੁਝ ਵਾਸਤੇ ਤਾਂ ਮਜ਼ੇਦਾਰ ਹੈ ਲੇਕਿਨ ਸਾਰਿਆਂ ਵਾਸਤੇ ਨਹੀਂ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"ਸਿਸਟਮ UI ਟਿਊਨਰ ਤੁਹਾਨੂੰ Android ਵਰਤੋਂਕਾਰ ਇੰਟਰਫ਼ੇਸ ਤਬਦੀਲ ਕਰਨ ਅਤੇ ਵਿਉਂਤਬੱਧ ਕਰਨ ਲਈ ਵਾਧੂ ਤਰੀਕੇ ਦਿੰਦਾ ਹੈ। ਇਹ ਪ੍ਰਯੋਗਾਤਮਿਕ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਭਵਿੱਖ ਦੀ ਰੀਲੀਜ਼ ਵਿੱਚ ਬਦਲ ਸਕਦੀਆਂ ਹਨ, ਟੁੱਟ ਸਕਦੀਆਂ ਹਨ, ਜਾਂ ਅਲੋਪ ਹੋ ਸਕਦੀਆਂ ਹਨ। ਸਾਵਧਾਨੀ ਨਾਲ ਅੱਗੇ ਵੱਧੋ।"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ਪ੍ਰਤੀਕ ਨੂੰ ਸਮੇਟੋ"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ਪ੍ਰਤੀਕ ਦਾ ਵਿਸਤਾਰ ਕਰੋ"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ਜਾਂ"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ਪਿੱਛੇ ਜਾਣ ਦਾ ਇਸ਼ਾਰਾ"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ਹੋਮ \'ਤੇ ਜਾਣ ਦਾ ਇਸ਼ਾਰਾ"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ਕਾਰਵਾਈ ਕੁੰਜੀ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index cf88172..1b27dba 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4811759950673118541">"UI systemu"</string>
+ <string name="app_label" msgid="4811759950673118541">"Interfejs systemu"</string>
<string name="battery_low_title" msgid="5319680173344341779">"Włączyć Oszczędzanie baterii?"</string>
<string name="battery_low_description" msgid="3282977755476423966">"Masz już tylko <xliff:g id="PERCENTAGE">%s</xliff:g> baterii. Oszczędzanie baterii uruchamia ciemny motyw, ogranicza aktywność w tle i opóźnia powiadomienia."</string>
<string name="battery_low_intro" msgid="5148725009653088790">"Oszczędzanie baterii uruchamia ciemny motyw, ogranicza aktywność w tle i opóźnia powiadomienia."</string>
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Aplikacja <xliff:g id="APPNAME">%1$s</xliff:g> i inne aplikacje wykryły ten zrzut ekranu."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Dodaj do notatek"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Dołącz link"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Nagrywanie ekranu"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Przetwarzam nagrywanie ekranu"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Stałe powiadomienie o sesji rejestrowania zawartości ekranu"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Wygaszacz ekranu"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Nie przeszkadzać"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Tryby priorytetowe"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Brak dostępnych sparowanych urządzeń"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Kliknij, aby podłączyć lub odłączyć urządzenie"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Używaj Bluetootha"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Połączone"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Udostępnianie dźwięku"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Kliknij, aby przełączyć lub udostępnić dźwięk"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Zapisane"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"rozłącz"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktywuj"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Otwórz Ustawienia"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Inne urządzenie"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Przełącz Przegląd"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Tryby priorytetowe"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gotowe"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ustawienia"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Wł."</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Podczas nagrywania i przesyłania usługa udostępniająca tę funkcję będzie miała dostęp do wszystkich informacji widocznych na ekranie lub odtwarzanych na urządzeniu. Dotyczy to m.in. haseł, szczegółów płatności, zdjęć, wiadomości i odtwarzanych dźwięków."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Udostępnianie i nagrywanie za pomocą aplikacji"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Udostępnić ekran aplikacji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Udostępnij jedną aplikację"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Udostępnij cały ekran"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Udostępnij jedną aplikację"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Udostępnij cały ekran"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kiedy udostępniasz treści z całego ekranu, aplikacja <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ma dostęp do całości obrazu z wyświetlacza. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, audio i filmów."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kiedy udostępniasz obraz z aplikacji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, widoczne jest wszystko to, co jest w niej wyświetlane lub odtwarzane. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, audio i filmów."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Udostępnij ekran"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelita – połączenie dobre"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelita – połączenie dostępne"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelitarne połączenie alarmowe"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Połączenia alarmowe lub SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil służbowy"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Dobra zabawa, ale nie dla każdego"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Kalibrator System UI udostępnia dodatkowe sposoby dostrajania i dostosowywania interfejsu Androida. Te eksperymentalne funkcje mogą się zmienić, popsuć lub zniknąć w przyszłych wersjach. Zachowaj ostrożność."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona zwijania"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona rozwijania"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"lub"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gest przejścia wstecz"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gest przejścia na ekran główny"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Klawisz działania"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index c2c40db..d5856af 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> e outros apps abertos detectaram essa captura de tela."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Incluir anotação"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Incluir link"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Gravador de tela"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processando gravação de tela"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação contínua para uma sessão de gravação de tela"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Protetor de tela"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Não perturbe"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modos prioritários"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Não há dispositivos pareados disponíveis"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Toque para conectar ou desconectar um dispositivo"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectado"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Compartilhamento de áudio"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Toque para mudar ou compartilhar o áudio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvo"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ativar"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Abrir as Configurações"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Outro dispositivo"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Alternar Visão geral"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos prioritários"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Concluído"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configurações"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Ativado"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"O serviço que oferece essa função terá acesso a todas as informações visíveis na tela ou reproduzidas durante uma gravação ou transmissão. Isso inclui senhas, detalhes de pagamento, fotos, mensagens e áudios."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Compartilhe ou grave um app"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Compartilhar a tela com o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Compartilhar um app"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Compartilhar a tela inteira"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Compartilhar um app"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Compartilhar a tela inteira"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Quando você compartilha a tela inteira, tudo nela fica visível para o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Quando você compartilha um aplicativo, todas as informações mostradas ou abertas nele ficam visíveis para o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Compartilhar tela"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, conexão boa"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexão disponível"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via satélite"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Chamadas de emergência ou SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabalho"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversão para alguns, mas não para todos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"O sintonizador System UI fornece maneiras adicionais de ajustar e personalizar a interface do usuário do Android. Esses recursos experimentais podem mudar, falhar ou desaparecer nas versões futuras. Prossiga com cuidado."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ícone \"Fechar\""</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ícone \"Abrir\""</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto de volta"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto de início"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de ação"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index c52354f..6589b0f 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"A app <xliff:g id="APPNAME">%1$s</xliff:g> e outras apps abertas detetaram esta captura de ecrã."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Adicionar a uma nota"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Incluir link"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Gravador de ecrã"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"A processar a gravação de ecrã"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação persistente de uma sessão de gravação de ecrã"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Proteção ecrã"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Não incomodar"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modos de prioridade"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Sem dispositivos sincronizados disponíveis"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Toque para associar ou desassociar um dispositivo"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ligado"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Partilha de áudio"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Toque para mudar ou partilhar o áudio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Guardado"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desassociar"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ativar"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Abrir definições"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Outro dispositivo"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Ativar/desativar Vista geral"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos de prioridade"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Concluir"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Definições"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Ativado"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"O serviço que fornece esta função vai ter acesso a todas as informações que estiverem visíveis no ecrã ou que forem reproduzidas a partir do dispositivo durante a gravação ou a transmissão. Isto inclui informações como palavras-passe, detalhes de pagamentos, fotos, mensagens e áudio reproduzido."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Partilhe ou grave uma app"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Partilhar o seu ecrã com a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Partilhar uma app"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Partilhar ecrã inteiro"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Partilhar uma app"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Partilhar ecrã inteiro"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Quando está a partilhar o ecrã inteiro, tudo o que estiver no ecrã é visível para a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Quando está a partilhar uma app, tudo o que é mostrado ou reproduzido nessa app é visível para a app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Partilhar ecrã"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, boa ligação"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, ligação disponível"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satélite SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Chamadas de emergência ou SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabalho"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversão para alguns, mas não para todos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"O Sintonizador da interface do sistema disponibiliza-lhe formas adicionais ajustar e personalizar a interface do utilizador do Android. Estas funcionalidades experimentais podem ser alteradas, deixar de funcionar ou desaparecer em versões futuras. Prossiga com cuidado."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ícone de reduzir"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ícone de expandir"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto para retroceder"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto para aceder ao ecrã principal"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de ação"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index c2c40db..d5856af 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> e outros apps abertos detectaram essa captura de tela."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Incluir anotação"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Incluir link"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Gravador de tela"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Processando gravação de tela"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação contínua para uma sessão de gravação de tela"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Protetor de tela"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Não perturbe"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modos prioritários"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Não há dispositivos pareados disponíveis"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Toque para conectar ou desconectar um dispositivo"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectado"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Compartilhamento de áudio"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Toque para mudar ou compartilhar o áudio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvo"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ativar"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Abrir as Configurações"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Outro dispositivo"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Alternar Visão geral"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modos prioritários"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Concluído"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Configurações"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Ativado"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"O serviço que oferece essa função terá acesso a todas as informações visíveis na tela ou reproduzidas durante uma gravação ou transmissão. Isso inclui senhas, detalhes de pagamento, fotos, mensagens e áudios."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Compartilhe ou grave um app"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Compartilhar a tela com o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Compartilhar um app"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Compartilhar a tela inteira"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Compartilhar um app"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Compartilhar a tela inteira"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Quando você compartilha a tela inteira, tudo nela fica visível para o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Quando você compartilha um aplicativo, todas as informações mostradas ou abertas nele ficam visíveis para o app <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Compartilhar tela"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, conexão boa"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexão disponível"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via satélite"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Chamadas de emergência ou SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabalho"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversão para alguns, mas não para todos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"O sintonizador System UI fornece maneiras adicionais de ajustar e personalizar a interface do usuário do Android. Esses recursos experimentais podem mudar, falhar ou desaparecer nas versões futuras. Prossiga com cuidado."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ícone \"Fechar\""</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ícone \"Abrir\""</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ou"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto de volta"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto de início"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tecla de ação"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 1f7b7164..59136e0 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> și alte aplicații deschise au detectat această captură de ecran."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Adaugă în notă"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Include linkul"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Recorder pentru ecran"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Se procesează înregistrarea"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificare în curs pentru o sesiune de înregistrare a ecranului"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Screensaver"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Nu deranja"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Moduri cu prioritate"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Niciun dispozitiv conectat disponibil"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Atinge pentru a conecta sau deconecta un dispozitiv"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Folosește Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectat"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Permiterea accesului la audio"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Atinge pentru a comuta sau a permite accesul la conținutul audio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvat"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"deconectează"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activează"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Deschide Setări"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Alt dispozitiv"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Comută secțiunea Recente"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Moduri cu prioritate"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Gata"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Setări"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Activat"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Serviciul care oferă această funcție va avea acces la toate informațiile vizibile pe ecran sau redate pe dispozitiv în timp ce înregistrezi sau proiectezi. Între aceste informații se numără parole, detalii de plată, fotografii, mesaje și conținutul audio pe care îl redai."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Permite accesul la o aplicație sau înregistreaz-o"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Permiți accesul <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> la ecran?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Permite accesul la o aplicație"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Permite accesul la tot ecranul"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Permite accesul la o aplicație"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Permite accesul la tot ecranul"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Când permiți accesul la tot ecranul, tot conținutul de pe ecran este vizibil pentru <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Când permiți accesul la o aplicație, orice conținut se afișează sau se redă în aplicație este vizibil pentru <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Permite accesul la ecran"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, conexiune bună"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, conexiune disponibilă"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS prin satelit"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Apeluri de urgență sau SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil de serviciu"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Distractiv pentru unii, dar nu pentru toată lumea"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner oferă modalități suplimentare de a ajusta și a personaliza interfața de utilizare Android. Aceste funcții experimentale pot să se schimbe, să se blocheze sau să dispară din versiunile viitoare. Continuă cu prudență."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Pictograma de restrângere"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Pictograma de extindere"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"sau"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gestul Înapoi"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gestul Ecran de pornire"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tastă de acțiuni"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 0b545ce..de43676 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Приложение \"<xliff:g id="APPNAME">%1$s</xliff:g>\" и другие запущенные продукты обнаружили создание скриншота."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Добавить в заметку"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Добавить ссылку"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Запись видео с экрана"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обработка записи с экрана…"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущее уведомление для записи видео с экрана"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Заставка"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Не беспокоить"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Режимы приоритета"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Нет доступных сопряженных устройств"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Нажмите, чтобы подключить или отключить устройство."</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Использовать"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Подключено"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Отправка аудио"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Нажмите, чтобы переключить аудио или поделиться им"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сохранено"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"отключить"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активировать"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Открыть настройки"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Другое устройство"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Переключить режим обзора"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Режимы приоритета"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Настройки"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Включено"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Во время записи или трансляции у сервиса, предоставляющего эту функцию, будет доступ ко всему, что видно или воспроизводится на устройстве, включая пароли, сведения о способах оплаты, фотографии, сообщения и аудио."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Демонстрация или запись экрана приложения"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Показать экран приложению \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\"?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Показать приложение"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Показать весь экран"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Показать приложение"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Показать весь экран"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"При показе экрана целиком все, что на нем происходит, будет видно в приложении \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\". Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"При показе приложения все, что в нем происходит, будет видно в приложении \"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>\". Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Показать экран"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Спутниковая связь, хорошее качество соединения"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Доступно соединение по спутниковой связи"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Спутниковый SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Экстренные вызовы или спутниковый SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Рабочий профиль"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Внимание!"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner позволяет настраивать интерфейс устройства Android по вашему вкусу. В будущем эта экспериментальная функция может измениться, перестать работать или исчезнуть."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Значок \"Свернуть\""</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Значок \"Развернуть\""</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"или"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Жест \"назад\""</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Жест \"на главный экран\""</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Клавиша действия"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index b34b8a3..8d6cd09 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> සහ අනෙකුත් විවෘත යෙදුම් මෙම තිර රුව අනාවරණය කර ගෙන ඇත."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"සටහනට එක් කරන්න"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"සබැඳිය ඇතුළත් කරන්න"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"තිර රෙකෝඩරය"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"තිර පටිගත කිරීම සකසමින්"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"තිර පටිගත කිරීමේ සැසියක් සඳහා කෙරෙන දැනුම් දීම"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"තිර සුරැකුම"</string>
<string name="ethernet_label" msgid="2203544727007463351">"ඊතර නෙට්"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"බාධා නොකරන්න"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"ප්රමුඛතා ප්රකාර"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"බ්ලූටූත්"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"යුගල කළ උපාංග නොතිබේ"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"උපාංගයක් සම්බන්ධ කිරීමට හෝ විසන්ධි කිරීමට තට්ටු කරන්න"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"බ්ලූටූත් භාවිතා කරන්න"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"සම්බන්ධිතයි"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ශ්රව්ය බෙදා ගැනීම"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ශ්රව්ය මාරු කිරීමට හෝ බෙදා ගැනීමට තට්ටු කරන්න"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"සුරැකිණි"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"විසන්ධි කරන්න"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"සක්රිය කරන්න"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"සැකසීම් විවෘත කරන්න"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"වෙනත් උපාංගය"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"දළ විශ්ලේෂණය ටොගල කරන්න"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ප්රමුඛතා ප්රකාර"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"නිමයි"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"සැකසීම්"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"ක්රියාත්මකයි"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"මෙම කාර්යය සපයන සේවාවට තිරයේ පෙනෙන හෝ පටිගත කිරීමේ දී හෝ විකාශනය කිරීමේ දී ඔබේ උපාංගයේ වාදනය වන සියලු තොරතුරු වෙත ප්රවේශය ඇත. මෙයට මුරපද, ගෙවීම් විස්තර, ඡායාරූප, පණිවුඩ, සහ ඔබ වාදනය කරන ශ්රව්ය වැනි තොරතුරු ඇතුළත් වේ."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"යෙදුමක් බෙදා ගන්න හෝ පටිගත කරන්න"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> සමග ඔබේ තිරය බෙදා ගන්න ද?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"එක් යෙදුමක් බෙදා ගන්න"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"සම්පූර්ණ තිරය බෙදා ගන්න"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"එක් යෙදුමක් බෙදා ගන්න"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"සම්පූර්ණ තිරය බෙදා ගන්න"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"ඔබ ඔබේ සම්පූර්ණ තිරය බෙදා ගන්නා විට, ඔබේ තිරයේ ඇති ඕනෑම දෙයක් <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> වෙත දෘශ්යමාන වේ. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවිඩ, ඡායාරූප, සහ ශ්රව්ය සහ දෘශ්ය වැනි දේවල් පිළිබඳ ප්රවේශම් වන්න."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"ඔබ යෙදුමක් බෙදා ගන්නා විට, එම යෙදුමේ පෙන්වන හෝ වාදනය කරන ඕනෑම දෙයක් <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> වෙත දෘශ්යමාන වේ. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවිඩ, ඡායාරූප, සහ ශ්රව්ය සහ දෘශ්ය වැනි දේවල් පිළිබඳ ප්රවේශම් වන්න."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"තිරය බෙදා ගන්න"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"චන්ද්රිකාව, හොඳ සම්බන්ධතාවයක්"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"චන්ද්රිකාව, සම්බන්ධතාවය තිබේ"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"චන්ද්රිකා SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"හදිසි ඇමතුම් හෝ SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"කාර්යාල පැතිකඩ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"සමහරක් දේවල් වලට විනෝදයි, නමුත් සියල්ලටම නොවේ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"පද්ධති UI සුසරකය ඔබට Android පරිශීලක අතුරු මුහුණත වෙනස් කිරීමට හෝ අභිරුචිකරණය කිරීමට අමතර ක්රම ලබා දේ. මෙම පර්යේෂණාත්මක අංග ඉදිරි නිකුත් වීම් වල වෙනස් වීමට, වැඩ නොකිරීමට, හෝ නැතිවීමට හැක. ප්රවේශමෙන් ඉදිරියට යන්න."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"හැකුළුම් නිරූපකය"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"දිගහැරීම් නිරූපකය"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"හෝ"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ආපසු අභිනය"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"නිවෙස් අභිනය"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ක්රියා යතුර"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index b1983b8..7159285 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> a ďalšie otvorené aplikácie zaznamenali túto snímku obrazovky."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Pridať do poznámky"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Zahrnúť odkaz"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Rekordér obrazovky"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Spracúva sa záznam obrazovky"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Zobrazuje sa upozornenie týkajúce sa relácie záznamu obrazovky"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Šetrič obrazovky"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Režim bez vyrušení"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Režimy priority"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Nie sú k dispozícii žiadne spárované zariadenia"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Klepnutím pripojíte alebo odpojíte zariadenie"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Používať Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Pripojené"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Zdieľanie zvuku"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Klepnutím prepnete alebo budete zdieľať zvuk"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Uložené"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"odpojiť"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivovať"</string>
@@ -389,7 +392,7 @@
<string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Rekordér obrazovky"</string>
<string name="performance" msgid="6552785217174378320">"Výkon"</string>
<string name="user_interface" msgid="3712869377953950887">"Používateľské rozhranie"</string>
- <string name="thermal" msgid="6758074791325414831">"Termálne"</string>
+ <string name="thermal" msgid="6758074791325414831">"Teplota"</string>
<string name="custom" msgid="3337456985275158299">"Vlastné"</string>
<string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Nastavenia vlastnej stopy"</string>
<string name="restore_default" msgid="5259420807486239755">"Obnoviť predvolené"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Otvoriť Nastavenia"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Iné zariadenie"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Prepnúť prehľad"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Režimy priority"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Hotovo"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nastavenia"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Zapnuté"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Služba poskytujúca túto funkciu bude mať prístup k všetkým informáciám zobrazovaným na obrazovke alebo prehrávaným v zariadení počas nahrávania či prenosu. Patria medzi ne informácie, ako sú heslá, platobné údaje, fotky, správy a prehrávaný zvuk."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Aplikácia na zdieľanie alebo nahrávanie"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Chcete zdieľať obrazovku s aplikáciou <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Zdieľať jednu aplikáciu"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Zdieľať celú obrazovku"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Zdieľať jednu aplikáciu"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Zdieľať celú obrazovku"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Pri zdieľaní celej obrazovky vidí aplikácia <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> všetko, čo sa na nej zobrazuje. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Pri zdieľaní aplikácie vidí aplikácia <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> všetko, čo sa v zdieľanej aplikácii zobrazuje alebo prehráva. Preto zvýšte pozornosť v prípade položiek, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Zdieľať obrazovku"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobrá kvalita pripojenia"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, pripojenie je k dispozícii"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Pomoc cez satelit"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Tiesňové volania alebo pomoc v tiesni"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Pracovný profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Pri používaní tuneru postupujte opatrne"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Tuner používateľského rozhrania systému poskytujte ďalšie spôsoby ladenia a prispôsobenia používateľského rozhrania Android. Tieto experimentálne funkcie sa môžu v budúcich verziách zmeniť, ich poskytovanie môže byť prerušené alebo môžu byť odstránené. Pokračujte opatrne."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona zbalenia"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona rozbalenia"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"alebo"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gesto prechodu späť"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gesto prechodu domov"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Akčný kláves"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index a3b042e..f2c466e 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> in druge odprte aplikacije so zaznale ta posnetek zaslona."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Dodaj v zapisek"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Vključi povezavo"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Snemalnik zaslona"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obdelava videoposnetka zaslona"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Nenehno obveščanje o seji snemanja zaslona"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Ohranjeval. zaslona"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ne moti"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prednostni načini"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Na voljo ni nobene seznanjene naprave"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Dotaknite se za vzpostavitev ali prekinitev povezave z napravo"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Uporabi Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Povezano"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Deljenje zvoka"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Dotaknite se za preklop ali deljenje zvoka"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Shranjeno"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekinitev povezave"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiviranje"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Odpri nastavitve"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Druga naprava"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Vklop/izklop pregleda"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prednostni načini"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Končano"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Nastavitve"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Vklopljeno"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Storitev, ki zagotavlja to funkcijo, bo imela dostop do vseh podatkov, ki so med snemanjem ali predvajanjem prikazani na vašem zaslonu ali se predvajajo iz vaše naprave. To vključuje podatke, kot so gesla, podrobnosti o plačilu, fotografije, sporočila in zvok, ki ga predvajate."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Deljenje ali snemanje aplikacije"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Želite deliti zaslon z aplikacijo <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Deli eno aplikacijo"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Deli celoten zaslon"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Deli eno aplikacijo"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Deli celoten zaslon"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Pri deljenju celotnega zaslona je aplikaciji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vidno vse na zaslonu. Zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Pri deljenju aplikacije je aplikaciji <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> vidno vse, kar je prikazano ali predvajano v tej aplikaciji. Zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Deli zaslon"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobra povezava"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, povezava je na voljo"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS prek satelita"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Klici v sili ali SOS prek satelita"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Delovni profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zabavno za nekatere, a ne za vse"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Uglaševalnik uporabniškega vmesnika sistema vam omogoča dodatne načine za spreminjanje in prilagajanje uporabniškega vmesnika Android. Te poskusne funkcije lahko v prihodnjih izdajah kadar koli izginejo, se spremenijo ali pokvarijo. Bodite previdni."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona za strnitev"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona za razširitev"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ali"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Poteza za pomik nazaj"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Poteza za začetni zaslon"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Gumb za dejanje"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 4cba527..70ea421 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> dhe aplikacionet e tjera të hapura zbuluan këtë pamje ekrani."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Shto te shënimi"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Përfshi lidhjen"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Regjistruesi i ekranit"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Regjistrimi i ekranit po përpunohet"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Njoftim i vazhdueshëm për një seancë regjistrimi të ekranit"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Mbrojtësi i ekranit"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Eternet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Mos shqetëso"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Modalitetet e përparësisë"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth-i"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Nuk ofrohet për përdorim asnjë pajisje e çiftuar"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Trokit për të lidhur ose shkëputur një pajisje"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Përdor Bluetooth-in"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Lidhur"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Ndarja e audios"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Trokit për të ndërruar ose ndarë audion"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Ruajtur"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"shkëput"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivizo"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Hap \"Cilësimet\""</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Pajisje tjetër"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Kalo te përmbledhja"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Modalitetet e përparësisë"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"U krye"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Cilësimet"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Aktiv"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Shërbimi që e ofron këtë funksion do të ketë qasje te të gjitha informacionet që janë të dukshme në ekran ose që luhen nga pajisja jote gjatë regjistrimit ose transmetimit. Kjo përfshin informacione, si p.sh.: fjalëkalimet, detajet e pagesave, fotografitë, mesazhet, si dhe audion që luan ti."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Ndaj ose regjistro një aplikacion"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Të ndahet ekrani yt me <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Ndaj një aplikacion"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Ndaj të gjithë ekranin"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Ndaj një aplikacion"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Ndaj të gjithë ekranin"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kur ti ndan të gjithë ekranin, çdo gjë në ekranin tënd është e dukshme për <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kur ti ndan një aplikacion, çdo gjë që shfaqet ose luhet në atë aplikacion është e dukshme për <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ndaj ekranin"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Sateliti. Lidhje e mirë"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Sateliti. Ofrohet lidhje"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS satelitor"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Telefonatat e urgjencës ose SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profili i punës"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Argëtim për disa, por jo për të gjithë!"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sintonizuesi i Sistemit të Ndërfaqes së Përdoruesit të jep mënyra shtesë për të tërhequr dhe personalizuar ndërfaqen Android të përdoruesit. Këto funksione eksperimentale mund të ndryshojnë, prishen ose zhduken në versionet e ardhshme. Vazhdo me kujdes."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona e palosjes"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona e zgjerimit"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"ose"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Gjesti i kthimit prapa"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Gjesti për të shkuar tek ekrani bazë"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Tasti i veprimit"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 26c135b..6db372d 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> и друге отворене апликације су откриле овај снимак екрана."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Додај у белешку"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Уврсти линк"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Снимач екрана"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обрађујемо видео снимка екрана"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Обавештење о сесији снимања екрана је активно"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Чувар екрана"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Етернет"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Не узнемиравај"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Приоритетни режими"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Није доступан ниједан упарени уређај"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Додирните да бисте повезали уређај или прекинули везу"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Користи Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Повезано"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Дељење звука"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Додирните да бисте пребацили или делили звук"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сачувано"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"прекините везу"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активирајте"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Отвори Подешавања"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Други уређај"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Укључи/искључи преглед"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Приоритетни режими"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Подешавања"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Укључено"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Услуга која пружа ову функцију ће имати приступ свим информацијама које се приказују на екрану или репродукују са уређаја током снимања или пребацивања. То обухвата информације попут лозинки, информација о плаћању, слика, порука и звука који пуштате."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Делите или снимите апликацију"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Желите да делите екран са апликацијом <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Дели једну апликацију"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Дели цео екран"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Дели једну апликацију"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Дели цео екран"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Када делите цео екран, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> види све што је на њему. Зато пазите на лозинке, информације о плаћању, поруке, слике, аудио и видео садржај."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Када делите апликацију, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> види сав садржај који се приказује или пушта у њој. Зато пазите на лозинке, информације о плаћању, поруке, слике, аудио и видео садржај."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Дели екран"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Сателит, веза је добра"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Сателит, веза је доступна"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Хитна помоћ преко сателита"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Хитни позиви или хитна помоћ"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Пословни профил"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Забава за неке, али не за све"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Тјунер за кориснички интерфејс система вам пружа додатне начине за подешавање и прилагођавање Android корисничког интерфејса. Ове експерименталне функције могу да се промене, откажу или нестану у будућим издањима. Будите опрезни."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Икона за скупљање"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Икона за проширивање"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"или"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Покрет за враћање"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Покрет за почетну страницу"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Тастер радњи"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 56cc442..225e3b3 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> och andra öppna appar identifierade skärmbilden."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Lägg till i anteckning"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Inkludera länk"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Skärminspelare"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Behandlar skärminspelning"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Avisering om att skärminspelning pågår"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Skärmsläckare"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Stör ej"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Prioriterade lägen"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Det finns inga kopplade enheter tillgängliga"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Tryck för att ansluta eller koppla från en enhet"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Använd Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ansluten"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Ljuddelning"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Tryck för att byta eller dela ljud"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Sparad"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"koppla från"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivera"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Öppna Inställningar"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Annan enhet"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aktivera och inaktivera översikten"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Prioriterade lägen"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Klar"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Inställningar"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"På"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Den tjänst som tillhandahåller funktionen får åtkomst till all information som visas på skärmen eller spelas upp från enheten när du spelar in eller castar. Detta omfattar till exempel lösenord, betalningsuppgifter, foton, meddelanden och ljud som du spelar upp."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Dela eller spela in en app"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Vill du dela skärmen med <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Dela en app"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Dela hela skärmen"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Dela en app"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Dela hela skärmen"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"När du delar hela skärmen är allt på skärmen synligt för <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton, ljud och video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"När du delar en app är allt som visas eller spelas upp i appen synligt för <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton, ljud och video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Dela skärmen"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellit, bra anslutning"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellit, anslutning tillgänglig"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS-larm via satellit"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Nödsamtal eller SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Jobbprofil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Kul för vissa, inte för alla"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Du kan använda inställningarna för systemgränssnitt för att justera användargränssnittet i Android. Dessa experimentfunktioner kan när som helst ändras, sluta fungera eller försvinna. Använd med försiktighet."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikonen Komprimera"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikonen Utöka"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"eller"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Tillbaka-rörelse"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Rörelse för att öppna startskärmen"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Åtgärdstangent"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index db237b5..9fa8e55 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> na zingine zinazotumika zimetambua picha hii ya skrini."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Ongeza kwenye dokezo"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Jumuisha kiungo"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g> <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Kinasa Skrini"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Inachakata rekodi ya skrini"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Arifa inayoendelea ya kipindi cha kurekodi skrini"</string>
@@ -124,7 +125,7 @@
<string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Inarekodi skrini na sauti"</string>
<string name="screenrecord_taps_label" msgid="1595690528298857649">"Onyesha sehemu za kugusa kwenye skrini"</string>
<string name="screenrecord_stop_label" msgid="72699670052087989">"Acha"</string>
- <string name="screenrecord_share_label" msgid="5025590804030086930">"Shiriki"</string>
+ <string name="screenrecord_share_label" msgid="5025590804030086930">"Tuma"</string>
<string name="screenrecord_save_title" msgid="1886652605520893850">"Imehifadhi rekodi ya skrini"</string>
<string name="screenrecord_save_text" msgid="3008973099800840163">"Gusa ili uangalie"</string>
<string name="screenrecord_save_error" msgid="5862648532560118815">"Hitilafu imetokea wakati wa kuhifadhi rekodi ya skrini"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Taswira ya skrini"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Usinisumbue"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Hali za kipaumbele"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Hakuna vifaa vilivyooanishwa vinavyopatikana"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Gusa ili uunganishe au utenganishe kifaa"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Tumia Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Imeunganishwa"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Kusikiliza Pamoja"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Gusa ili ubadilishe sauti au usikilize pamoja na wengine"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Imehifadhiwa"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ondoa"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"anza kutumia"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Fungua Mipangilio"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Kifaa kingine"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Washa Muhtasari"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Hali za kipaumbele"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Nimemaliza"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Mipangilio"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Imewashwa"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Huduma inayotoa utendaji huu itaweza kufikia maelezo yote yanayoonekana kwenye skrini yako au yanayochezwa kwenye kifaa chako wakati wa kurekodi au kutuma. Hii ni pamoja na maelezo kama vile manenosiri, maelezo ya malipo, picha, ujumbe na sauti unayocheza."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Kurekodi au kuruhusu programu ifikiwe"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Ungependa kuruhusu <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ifikie skrini yako?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Ruhusu ufikiaji wa programu moja"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Ruhusu ufikiaji wa skrini nzima"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Ruhusu ufikiaji wa programu moja"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Ruhusu ufikiaji wa skrini nzima"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Unaporuhusu ufikiaji wa skrini nzima, chochote kilicho katika skrini yako kitaonekana kwa <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha, sauti na video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Unaporuhusu ufikiaji wa programu, chochote kinachoonyeshwa au kuchezwa katika programu hiyo kitaonekana kwa <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha, sauti na video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ruhusu ufikiaji wa skrini"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Setilaiti, muunganisho thabiti"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Setilaiti, muunganisho unapatikana"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Msaada kupitia Setilaiti"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Simu za dharura"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Wasifu wa kazini"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Kinafurahisha kwa baadhi ya watu lakini si wote"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Kirekebishi cha kiolesura cha mfumo kinakupa njia zaidi za kugeuza na kubadilisha kiolesura cha Android ili kikufae. Vipengele hivi vya majaribio vinaweza kubadilika, kuharibika au kupotea katika matoleo ya siku zijazo. Endelea kwa uangalifu."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Kunja aikoni"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Panua aikoni"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"au"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Ishara ya kurudi nyuma"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Mguso wa kurudi kwenye skrini ya kwanza"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Kitufe cha vitendo"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index e617e88..7acd1e8 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"இந்த ஸ்கிரீன்ஷாட்டை <xliff:g id="APPNAME">%1$s</xliff:g> மற்றும் திறந்திருக்கும் பிற ஆப்ஸ் கண்டறிந்துள்ளன."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"குறிப்பில் சேர்"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"இணைப்பைச் சேர்"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"ஸ்கிரீன் ரெக்கார்டர்"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"ஸ்க்ரீன் ரெக்கார்டிங் செயலாக்கப்படுகிறது"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"திரை ரெக்கார்டிங் அமர்விற்கான தொடர் அறிவிப்பு"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"ஸ்கிரீன் சேவர்"</string>
<string name="ethernet_label" msgid="2203544727007463351">"ஈதர்நெட்"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"தொந்தரவு செய்ய வேண்டாம்"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"முன்னுரிமைப் பயன்முறைகள்"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"புளூடூத்"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"இணைக்கப்பட்ட சாதனங்கள் இல்லை"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"சாதனத்தை இணைக்க/துண்டிக்க தட்டவும்"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"புளூடூத்தைப் பயன்படுத்துதல்"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"இணைக்கப்பட்டது"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ஆடியோ பகிர்வு"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ஆடியோவை மாற்ற அல்லது பகிர, தட்டவும்"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"சேமிக்கப்பட்டது"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"இணைப்பு நீக்கும்"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"செயல்படுத்தும்"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"அமைப்புகளைத் திற"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"பிற சாதனம்"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"மேலோட்டப் பார்வையை நிலைமாற்று"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"முன்னுரிமைப் பயன்முறைகள்"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"முடிந்தது"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"அமைப்புகள்"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"இயக்கப்பட்டுள்ளது"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"ரெக்கார்டு செய்யும்போதோ அலைபரப்பும்போதோ உங்கள் திரையில் காட்டப்படுகின்ற அல்லது சாதனத்திலிருந்து பிளே செய்யப்படுகின்ற அனைத்துத் தகவல்களையும் இந்தச் செயல்பாட்டை வழங்கும் சேவையால் அணுக முடியும். கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், படங்கள், மெசேஜ்கள், நீங்கள் பிளே செய்யும் ஆடியோ போன்றவை இதிலடங்கும்."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"ஆப்ஸைப் பகிர்தல் அல்லது ரெக்கார்டு செய்தல்"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> உடன் திரையைப் பகிரவா?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ஓர் ஆப்ஸைப் பகிர்"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"முழுத் திரையையும் பகிர்"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"ஓர் ஆப்ஸைப் பகிர்"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"முழுத் திரையையும் பகிர்"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"உங்கள் முழுத்திரையையும் பகிரும்போது, திரையில் உள்ள அனைத்தும் <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> இல் தெரியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"ஓர் ஆப்ஸைப் பகிரும்போது, அதில் காட்டப்படும்/பிளே செய்யப்படும் அனைத்தும் <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> இல் தெரியும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"திரையைப் பகிர்"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"சாட்டிலைட், நிலையான இணைப்பு"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"சாட்டிலைட், இணைப்பு கிடைக்கிறது"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"சாட்டிலைட் SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"அவசர அழைப்புகள் அல்லது SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"பணிக் கணக்கு"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"சில வேடிக்கையாக இருந்தாலும் கவனம் தேவை"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner, Android பயனர் இடைமுகத்தை மாற்றவும் தனிப்பயனாக்கவும் கூடுதல் வழிகளை வழங்குகிறது. இந்தப் பரிசோதனைக்குரிய அம்சங்கள் எதிர்கால வெளியீடுகளில் மாற்றப்படலாம், இடைநிறுத்தப்படலாம் அல்லது தோன்றாமல் போகலாம். கவனத்துடன் தொடரவும்."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"சுருக்குவதற்கான ஐகான்"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"விரிவாக்குவதற்கான ஐகான்"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"அல்லது"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"பின்செல்வதற்கான சைகை"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"முகப்பிற்குச் செல்வதற்கான சைகை"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ஆக்ஷன் பட்டன்"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index b45e82b..5cba2ef 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g>, ఇతర ఓపెన్ యాప్లు ఈ స్క్రీన్షాట్ను గుర్తించాయి."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"గమనికకు జోడించండి"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"లింక్ను చేర్చండి"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"స్క్రీన్ రికార్డర్"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"స్క్రీన్ రికార్డింగ్ అవుతోంది"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"స్క్రీన్ రికార్డ్ సెషన్ కోసం ఆన్గోయింగ్ నోటిఫికేషన్"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"స్క్రీన్ సేవర్"</string>
<string name="ethernet_label" msgid="2203544727007463351">"ఈథర్నెట్"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"అంతరాయం కలిగించవద్దు"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"ముఖ్యమైన ఫైల్స్ మోడ్స్"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"బ్లూటూత్"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"జత చేసిన పరికరాలు ఏవీ అందుబాటులో లేవు"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"పరికరాన్ని కనెక్ట్ చేయడానికి లేదా డిస్కనెక్ట్ చేయడానికి ట్యాప్ చేయండి"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"బ్లూటూత్ వాడండి"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"కనెక్ట్ అయింది"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ఆడియో షేరింగ్"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"ఆడియోను మార్చడానికి లేదా షేర్ చేయడానికి ట్యాప్ చేయండి"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"సేవ్ అయ్యింది"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"డిస్కనెక్ట్ చేయండి"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"యాక్టివేట్ చేయండి"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"సెట్టింగ్లను తెరవండి"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"ఇతర పరికరం"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"స్థూలదృష్టిని టోగుల్ చేయి"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ముఖ్యమైన ఫైళ్ల మోడ్స్"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"పూర్తయింది"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"సెట్టింగ్లు"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"ఆన్లో ఉంది"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"రికార్డ్ చేస్తున్నప్పుడు లేదా ప్రసారం చేస్తున్నప్పుడు మీ స్క్రీన్పై చూపబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన సమాచారం మొత్తాన్ని, ఈ ఫంక్షన్ను అందిస్తున్న సర్వీస్ యాక్సెస్ చేయగలదు. ఈ సమాచారంలో, పాస్వర్డ్లు, పేమెంట్ వివరాలు, ఫోటోలు, మెసేజ్లు, మీరు ప్లే చేసే ఆడియో వంటివి ఉంటాయి."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"యాప్ను షేర్ చేయండి లేదా రికార్డ్ చేయండి"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"మీ స్క్రీన్ను <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>తో షేర్ చేయండి?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ఒక యాప్ను షేర్ చేయండి"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"మొత్తం స్క్రీన్ను షేర్ చేయండి"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"ఒక యాప్ను షేర్ చేయండి"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"మొత్తం స్క్రీన్ను షేర్ చేయండి"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"మీ మొత్తం స్క్రీన్ను మీరు షేర్ చేసేటప్పుడు, మీ స్క్రీన్పై ఉన్నవన్నీ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>కు కనిపిస్తాయి. కాబట్టి పాస్వర్డ్లు, పేమెంట్ వివరాలు, మెసేజ్లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"మీరు యాప్ను షేర్ చేసేటప్పుడు, సంబంధిత యాప్లో కనిపించేవి లేదా ప్లే అయ్యేవన్నీ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>కు కనిపిస్తాయి. కాబట్టి పాస్వర్డ్లు, పేమెంట్ వివరాలు, మెసేజ్లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"స్క్రీన్ను షేర్ చేయండి"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"శాటిలైట్, కనెక్షన్ బాగుంది"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"శాటిలైట్, కనెక్షన్ అందుబాటులో ఉంది"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"ఎమర్జెన్సీ శాటిలైట్ సహాయం"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ఎమర్జెన్సీ కాల్స్ లేదా SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ఆఫీస్ ప్రొఫైల్"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"కొందరికి సరదాగా ఉంటుంది కానీ అందరికీ అలాగే ఉండదు"</string>
<string name="tuner_warning" msgid="1861736288458481650">"సిస్టమ్ UI ట్యూనర్ Android వినియోగదారు ఇంటర్ఫేస్ను మెరుగుపరచడానికి మరియు అనుకూలంగా మార్చడానికి మీకు మరిన్ని మార్గాలను అందిస్తుంది. ఈ ప్రయోగాత్మక లక్షణాలు భవిష్యత్తు విడుదలల్లో మార్పుకు లోనవ్వచ్చు, తాత్కాలికంగా లేదా పూర్తిగా నిలిపివేయవచ్చు. జాగ్రత్తగా కొనసాగండి."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"కుదించండి చిహ్నం"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"విస్తరించండి చిహ్నం"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"లేదా"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"వెనుకకు పంపే సంజ్ఞ"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"హోమ్కు పంపే సంజ్ఞ"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"యాక్షన్ కీ"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 252fc05..905ab98 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> และแอปอื่นๆ ที่เปิดอยู่ตรวจพบภาพหน้าจอนี้"</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"เพิ่มลงในโน้ต"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"รวมลิงก์"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"โปรแกรมบันทึกหน้าจอ"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"กำลังประมวลผลการอัดหน้าจอ"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"การแจ้งเตือนต่อเนื่องสำหรับเซสชันการบันทึกหน้าจอ"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"ภาพพักหน้าจอ"</string>
<string name="ethernet_label" msgid="2203544727007463351">"อีเทอร์เน็ต"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"ห้ามรบกวน"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"โหมดสำคัญ"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"บลูทูธ"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"ไม่มีอุปกรณ์ที่จับคู่ที่สามารถใช้ได้"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"แตะเพื่อเชื่อมต่อหรือยกเลิกการเชื่อมต่ออุปกรณ์"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ใช้บลูทูธ"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"เชื่อมต่อแล้ว"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"การแชร์เสียง"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"แตะเพื่อสลับหรือแชร์เสียง"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"บันทึกแล้ว"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ยกเลิกการเชื่อมต่อ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"เปิดใช้งาน"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"เปิดการตั้งค่า"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"อุปกรณ์อื่น"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"สลับภาพรวม"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"โหมดสำคัญ"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"เสร็จสิ้น"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"การตั้งค่า"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"เปิด"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"บริการที่มีฟังก์ชันนี้จะมีสิทธิ์เข้าถึงข้อมูลทั้งหมดที่ปรากฏบนหน้าจอหรือเปิดจากอุปกรณ์ของคุณขณะบันทึกหรือแคสต์ ซึ่งรวมถึงข้อมูลอย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน รูปภาพ ข้อความ และเสียงที่คุณเล่น"</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"แชร์หรือบันทึกแอป"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"แชร์หน้าจอกับ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ไหม"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"แชร์แอปเดียว"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"แชร์ทั้งหน้าจอ"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"แชร์แอปเดียว"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"แชร์ทั้งหน้าจอ"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"เมื่อกำลังแชร์ทั้งหน้าจอ <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> จะมองเห็นทุกสิ่งที่อยู่บนหน้าจอ ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"เมื่อกำลังแชร์แอป <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> จะมองเห็นทุกสิ่งที่แสดงหรือเล่นอยู่ในแอปดังกล่าว ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"แชร์หน้าจอ"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ดาวเทียม, การเชื่อมต่อดี"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ดาวเทียม, การเชื่อมต่อที่พร้อมใช้งาน"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS ดาวเทียม"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"การโทรฉุกเฉินหรือ SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"โปรไฟล์งาน"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"เพลิดเพลินกับบางส่วนแต่ไม่ใช่ทั้งหมด"</string>
<string name="tuner_warning" msgid="1861736288458481650">"ตัวรับสัญญาณ UI ระบบช่วยให้คุณมีวิธีพิเศษในการปรับแต่งและกำหนดค่าส่วนติดต่อผู้ใช้ Android ฟีเจอร์รุ่นทดลองเหล่านี้อาจมีการเปลี่ยนแปลง ขัดข้อง หรือหายไปในเวอร์ชันอนาคต โปรดดำเนินการด้วยความระมัดระวัง"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ไอคอนยุบ"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"ไอคอนขยาย"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"หรือ"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"ท่าทางสัมผัสสำหรับย้อนกลับ"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ท่าทางสัมผัสสำหรับหน้าแรก"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ปุ่มดำเนินการ"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 04f52ea..5e9d720 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"Na-detect ng <xliff:g id="APPNAME">%1$s</xliff:g> at ng iba pang bukas na app ang screenshot na ito."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Idagdag sa tala"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Isama ang link"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Recorder ng Screen"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Pinoproseso screen recording"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Kasalukuyang notification para sa session ng pag-record ng screen"</string>
@@ -291,7 +292,7 @@
<string name="start_dreams" msgid="9131802557946276718">"Screen saver"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Huwag Istorbohin"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Mga mode ng priyoridad"</string>
+ <string name="quick_settings_modes_label" msgid="879156359479504244">"Mga Mode"</string>
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Walang available na mga magkapares na device"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Mag-tap para magkonekta o magdiskonekta ng device"</string>
@@ -300,6 +301,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Gumamit ng Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Nakakonekta"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Pag-share ng Audio"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"I-tap para lumipat o magbahagi ng audio"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Na-save"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"idiskonekta"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"i-activate"</string>
@@ -431,7 +433,7 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Buksan ang Mga Setting"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Iba pang device"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"I-toggle ang Overview"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Mga priyoridad na mode"</string>
+ <string name="zen_modes_dialog_title" msgid="8854640808100096934">"Mga Mode"</string>
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Tapos na"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Mga Setting"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Naka-on"</string>
@@ -532,8 +534,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Ang serbisyong nagbibigay ng function na ito ay magkakaroon ng access sa lahat ng impormasyong nakikita sa iyong screen o pine-play mula sa device mo habang nagre-record o nagka-cast. Kasama rito ang impormasyong tulad ng mga password, detalye ng pagbabayad, larawan, mensahe, at audio na pine-play mo."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Magbahagi o mag-record ng app"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Ibahagi ang iyong screen sa <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Magbahagi ng isang app"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Ibahagi ang buong screen"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Mag-share ng isang app"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"I-share ang buong screen"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Kapag ibinahagi mo ang iyong buong screen, makikita ng <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ang kahit anong nasa screen mo. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Kapag nagbabahagi ka ng app, makikita ng <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ang kahit anong ipinapakita o pine-play sa app na iyon. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ibahagi ang screen"</string>
@@ -629,7 +635,7 @@
<string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Mga Setting"</string>
<string name="volume_panel_captioning_title" msgid="5984936949147684357">"Instant Caption"</string>
<string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Ibinaba sa mas ligtas na level ang volume"</string>
- <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Naging malakas ang volume ng headphones nang mas matagal sa inirerekomenda"</string>
+ <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Malakas ang volume ng headphones nang mas matagal sa inirerekomenda"</string>
<string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Lampas na sa ligtas na limitasyon para sa linggong ito ang volume ng headphone"</string>
<string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Magpatuloy sa pakikinig"</string>
<string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Hinaan"</string>
@@ -718,8 +724,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, malakas ang koneksyon"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, may koneksyon"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Mga emergency na tawag o SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profile sa trabaho"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Masaya para sa ilan ngunit hindi para sa lahat"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Nagbibigay sa iyo ang Tuner ng System UI ng mga karagdagang paraan upang baguhin at i-customize ang user interface ng Android. Ang mga pang-eksperimentong feature na ito ay maaaring magbago, masira o mawala sa mga pagpapalabas sa hinaharap. Magpatuloy nang may pag-iingat."</string>
@@ -1386,6 +1391,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"I-collapse ang icon"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"I-expand ang icon"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"o"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Galaw para bumalik"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Galaw para sa Home"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Action key"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 19c9e0c..db49402 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> ve diğer açık uygulamalar bu ekran görüntüsünü algıladı."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Nota ekle"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Bağlantıyı dahil et"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Ekran Kaydedicisi"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran kaydı işleniyor"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekran kaydı oturumu için devam eden bildirim"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Ekran koruyucu"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Rahatsız Etmeyin"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Öncelik modları"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Kullanılabilir eşlenmiş cihaz yok"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Cihaz bağlamak veya cihazın bağlantısını kesmek için dokunun"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth\'u kullan"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Bağlandı"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Ses Paylaşımı"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Geçiş yapmak veya ses paylaşmak için dokunun"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Kaydedildi"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"bağlantıyı kes"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"etkinleştir"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Ayarlar\'ı aç"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Diğer cihaz"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Genel bakışı aç/kapat"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Öncelik modları"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Bitti"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Ayarlar"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Açık"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Bu işlevi sağlayan hizmet, ekranınızda görünen veya kayıt ya da yayın sırasında cihazınızdan oynatılan tüm bilgilere erişecektir. Bu bilgiler arasında şifreler, ödeme detayları, fotoğraflar, mesajlar ve çaldığınız sesler gibi bilgiler yer alır."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Uygulamayı paylaşın veya kaydedin"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Ekranınız <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> uygulamasıyla paylaşılsın mı?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Tek bir uygulamayı paylaş"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Tüm ekranı paylaş"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Tek bir uygulamayı paylaş"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Tüm ekranı paylaş"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, tüm ekranınızı paylaştığınızda ekranınızdaki her şeyi görebilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>, bir uygulamayı paylaştığınızda o uygulamada gösterilen veya oynatılan her şeyi görebilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ekranı paylaş"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Uydu, bağlantı güçlü"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Uydu, bağlantı mevcut"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Acil Uydu Bağlantısı"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Acil durum aramaları veya acil yardım"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"İş profili"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Bazıları için eğlenceliyken diğerleri için olmayabilir"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sistem Kullanıcı Arayüzü Ayarlayıcı, Android kullanıcı arayüzünde değişiklikler yapmanız ve arayüzü özelleştirmeniz için ekstra yollar sağlar. Bu deneysel özellikler değişebilir, bozulabilir veya gelecekteki sürümlerde yer almayabilir. Dikkatli bir şekilde devam edin."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Daralt simgesi"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Genişlet simgesi"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"veya"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Geri hareketi"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Ana sayfa hareketi"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Eylem tuşu"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 8af4120..6d881df 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> та інші відкриті додатки виявили цей знімок екрана."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Додати до примітки"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Додати посилання"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Запис відео з екрана"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Обробка записування екрана"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Сповіщення про сеанс запису екрана"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Заставка"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Не турбувати"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Режими пріоритету"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Немає спарених пристроїв"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Натисніть, щоб під’єднати або від’єднати пристрій"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Увімкнути Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Підключено"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Надсилання аудіо"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Натисніть, щоб змінити режим або надіслати аудіо"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Збережено"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"від’єднати"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активувати"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Відкрити налаштування"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Інший пристрій"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Увімкнути або вимкнути огляд"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Режими пріоритету"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Готово"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Налаштування"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Увімкнено"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Сервіс, що надає цю функцію, матиме доступ до всієї інформації, яка з’являється на екрані або відтворюється на пристрої під час запису чи трансляції, зокрема до паролів, платіжної інформації, фотографій, повідомлень і аудіофайлів."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Показувати або записувати додаток"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Показати екран для додатка <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Показати один додаток"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Показати весь екран"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Показати один додаток"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Показати весь екран"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Коли ви показуєте весь екран, для додатка <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> стає видимим увесь контент на ньому. Тому будьте обережні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Коли ви показуєте додаток, для додатка <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> стає видимим увесь контент, що відображається або відтворюється в ньому. Тому будьте обережні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Показати екран"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Хороше з’єднання із супутником"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Доступне з’єднання із супутником"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Супутниковий сигнал SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Екстрені виклики або сигнал SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Робочий профіль"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Це цікаво, але будьте обачні"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner пропонує нові способи налаштувати та персоналізувати інтерфейс користувача Android. Ці експериментальні функції можуть змінюватися, не працювати чи зникати в майбутніх версіях. Будьте обачні."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Значок згортання"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Значок розгортання"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"або"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Жест \"Назад\""</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Жест переходу на головний екран"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Клавіша дії"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index dd27515..628d660 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> اور دیگر کھلی ایپس نے اس اسکرین شاٹ کا پتا لگایا۔"</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"نوٹ میں شامل کریں"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"لنک شامل کریں"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"اسکرین ریکارڈر"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"سکرین ریکارڈنگ پروسیس ہورہی ہے"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"اسکرین ریکارڈ سیشن کیلئے جاری اطلاع"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"اسکرین سیور"</string>
<string name="ethernet_label" msgid="2203544727007463351">"ایتھرنیٹ"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"ڈسٹرب نہ کریں"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"ترجیحی وضع"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"بلوٹوتھ"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"کوئی جوڑا بنائے ہوئے آلات دستیاب نہیں ہیں"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"کسی آلے کو منسلک یا غیر منسلک کرنے کے لیے تھپتھپائیں"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"بلوٹوتھ استعمال کریں"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"منسلک ہے"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"آڈیو کا اشتراک"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"آڈیو پر سوئچ کرنے یا اس کا اشتراک کرنے کے لیے تھپتھپائیں"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"محفوظ ہے"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"غیر منسلک کریں"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"فعال کریں"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"ترتیبات کھولیں"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"دوسرا آلہ"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"مجموعی جائزہ ٹوگل کریں"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"ترجیحی وضع"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"ہو گیا"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ترتیبات"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"آن ہے"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"اس فنکشن فراہم کرنے والی سروس کو اس تمام معلومات تک رسائی حاصل ہوگی جو آپ کی اسکرین پر نظر آتی ہے یا ریکارڈنگ یا کاسٹنگ کے دوران آپ کے آلے سے چلائی گئی ہے۔ اس میں پاس ورڈز، ادائیگی کی تفصیلات، تصاویر، پیغامات اور آپ کے ذریعے چلائی جانے والی آڈیو جیسی معلومات شامل ہے۔"</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"ایپ کا اشتراک یا ریکارڈ کریں"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کے ساتھ اپنی اسکرین کا اشتراک کریں؟"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"ایک ایپ کا اشتراک کریں"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"پوری اسکرین کا اشتراک کریں"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"ایک ایپ کا اشتراک کریں"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"پوری اسکرین کا اشتراک کریں"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"آپ کے اپنی پوری اسکرین کا اشتراک کرنے پر آپ کی اسکرین پر ہر چیز <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کیلئے مرئی ہوجاتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"آپ کے کسی ایپ کا اشتراک کرنے پر اس ایپ میں دکھائی گئی یا چلائی گئی ہر چیز <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> کیلئے مرئی ہو جاتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"اسکرین کا اشتراک کریں"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"سیٹلائٹ، کنکشن اچھا ہے"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"سیٹلائٹ، کنکشن دستیاب ہے"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"سیٹلائٹ SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ایمرجنسی کالز یا SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"دفتری پروفائل"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"کچھ کیلئے دلچسپ لیکن سبھی کیلئے نہیں"</string>
<string name="tuner_warning" msgid="1861736288458481650">"سسٹم UI ٹیونر Android صارف انٹر فیس میں ردوبدل کرنے اور اسے حسب ضرورت بنانے کیلئے آپ کو اضافی طریقے دیتا ہے۔ یہ تجرباتی خصوصیات مستقبل کی ریلیزز میں تبدیل ہو سکتی، رک سکتی یا غائب ہو سکتی ہیں۔ احتیاط کے ساتھ آگے بڑھیں۔"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"آئیکن سکیڑیں"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"آئیکن پھیلائیں"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"یا"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"پیچھے جانے کا اشارہ"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"ہوم کا اشارہ"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"ایکشن کلید"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index b0ba287..f0988ed 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> va boshqa ochiq ilovalar skrinshot olinganini aniqladi."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Qaydga qoʻshish"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Havolani kiritish"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g>, <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Ekranni yozib olish"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekran yozib olinmoqda"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekrandan yozib olish seansi uchun joriy bildirishnoma"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Ekran lavhasi"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Bezovta qilinmasin"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Muhim rejimlar"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Ulangan qurilmalar topilmadi"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Qurilma ulash yoki uzish uchun tegining"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth ishlatish"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ulangan"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio ulashuvi"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Audioni almashtirish yoki ulashish uchun bosing"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saqlangan"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"uzish"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"faollashtirish"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Sozlamalarni ochish"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Boshqa qurilma"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Umumiy nazar rejimini almashtirish"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Muhim rejimlar"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Tayyor"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Sozlamalar"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Yoniq"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Bu funksiyani taʼminlovchi xizmat ekranda chiqqan yoki yozib olish va translatsiya vaqtida ijro etilgan barcha axborotlarga ruxsat oladi. Bu axborotlar parollar, toʻlov tafsilotlari, rasmlar, xabarlar va ijro etilgan audiolardan iborat boʻlishi mumkin."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Ilovani ulashish yoki yozib olish"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Ekraningiz <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> bilan ulashilsinmi?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Bitta ilovani namoyish qilish"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Butun ekranni namoyish qilish"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Bitta ilovani namoyish qilish"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Butun ekranni namoyish qilish"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Butun ekranni namoyish qilayotganingizda, ekrandagi barcha narsalaringiz <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ga koʻrinadi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Ilovani namoyish qilayotganingizda oʻsha ilova ichida koʻrsatilayotgan yoki ijro qilinayotganlar <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>ga koʻrinadi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Ekranni namoyish qilish"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Sputnik, aloqa sifati yaxshi"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Sputnik, aloqa mavjud"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Sputnik SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Favqulodda chaqiruvlar yoki SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Ish profili"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diqqat!"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner yordamida siz Android foydalanuvchi interfeysini tuzatish va o‘zingizga moslashtirishingiz mumkin. Ushbu tajribaviy funksiyalar o‘zgarishi, buzilishi yoki keyingi versiyalarda olib tashlanishi mumkin. Ehtiyot bo‘lib davom eting."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Yigʻish belgisi"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Yoyish belgisi"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"yoki"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Orqaga qaytish ishorasi"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Asosiy ekran ishorasi"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Amal tugmasi"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index b6c6967..6ad5db4 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> và các ứng dụng đang mở khác đã phát hiện thấy ảnh chụp màn hình này."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Thêm vào ghi chú"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Thêm đường liên kết"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Trình ghi màn hình"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Đang xử lý video ghi màn hình"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Thông báo đang diễn ra về phiên ghi màn hình"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Trình bảo vệ m.hình"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Không làm phiền"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Chế độ ưu tiên"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Không có thiết bị nào được ghép nối"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Nhấn để kết nối/ngắt kết nối với một thiết bị"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bật Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Đã kết nối"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Chia sẻ âm thanh"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Nhấn để chuyển hoặc chia sẻ âm thanh"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Đã lưu"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ngắt kết nối"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"kích hoạt"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Mở phần Cài đặt"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Thiết bị khác"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Bật/tắt chế độ xem Tổng quan"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Chế độ ưu tiên"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Xong"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Cài đặt"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Đang bật"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Dịch vụ cung cấp chức năng này có quyền truy cập vào tất cả thông tin xuất hiện trên màn hình của bạn hoặc phát trên thiết bị của bạn trong khi ghi hoặc truyền, bao gồm cả thông tin như mật khẩu, thông tin thanh toán, ảnh, tin nhắn và âm thanh mà bạn phát."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Chia sẻ hoặc ghi một ứng dụng"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Chia sẻ màn hình của bạn với <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Chia sẻ một ứng dụng"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Chia sẻ toàn bộ màn hình"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Chia sẻ một ứng dụng"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Chia sẻ toàn bộ màn hình"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Khi bạn chia sẻ toàn bộ màn hình, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sẽ thấy được mọi nội dung trên màn hình của bạn. Vì vậy, hãy thận trọng để không làm lộ thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Khi bạn chia sẻ một ứng dụng, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> sẽ thấy được mọi nội dung hiển thị hoặc phát trong ứng dụng đó. Vì vậy, hãy thận trọng để không làm lộ thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Chia sẻ màn hình"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Kết nối vệ tinh tốt"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Hiện có kết nối vệ tinh"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Liên lạc khẩn cấp qua vệ tinh"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Cuộc gọi khẩn cấp hoặc SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Hồ sơ công việc"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Thú vị đối với một số người nhưng không phải tất cả"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Bộ điều hướng giao diện người dùng hệ thống cung cấp thêm cho bạn những cách chỉnh sửa và tùy chỉnh giao diện người dùng Android. Những tính năng thử nghiệm này có thể thay đổi, hỏng hoặc biến mất trong các phiên bản tương lai. Hãy thận trọng khi tiếp tục."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Biểu tượng Thu gọn"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Biểu tượng Mở rộng"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"hoặc"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Cử chỉ quay lại"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Cử chỉ chuyển đến màn hình chính"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Phím hành động"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 9ce05a3..35f8851 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -104,10 +104,11 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> 及其他打开的应用检测到此屏幕截图。"</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"添加到备注中"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"包括链接"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"屏幕录制器"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"正在处理屏幕录制视频"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"持续显示屏幕录制会话通知"</string>
- <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"要录制屏幕?"</string>
+ <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"要录制屏幕吗?"</string>
<string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"录制单个应用"</string>
<string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="2794896384693120020">"录制整个屏幕"</string>
<string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"录制整个屏幕时,屏幕上显示的所有内容均会被录制。因此,请务必小心操作,谨防泄露密码、付款信息、消息、照片、音频、视频等。"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"屏保"</string>
<string name="ethernet_label" msgid="2203544727007463351">"有线网络"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"勿扰"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"优先模式"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"蓝牙"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"没有可用的配对设备"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"点按即可连接设备或断开设备连接"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"启用蓝牙"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"已连接"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"音频分享"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"点按即可切换或分享音频"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"已保存"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"断开连接"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"启用"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"打开“设置”"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"其他设备"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切换概览"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"优先模式"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"完成"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"设置"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"已开启"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"在录制或投放内容时,提供此功能的服务将可访问屏幕上显示或设备中播放的所有信息,其中包括密码、付款信息、照片、消息及播放的音频等信息。"</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"分享或录制应用"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"要与“<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>”共享屏幕吗?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"共享一个应用"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"共享整个屏幕"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"共享一个应用"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"共享整个屏幕"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"当您共享整个屏幕时,屏幕上的所有内容均对“<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>”可见。因此,请务必小心操作,谨防泄露密码、付款信息、消息、照片、音频、视频等。"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"当您共享一个应用时,该应用中显示或播放的所有内容均对“<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>”可见。因此,请务必小心操作,谨防泄露密码、付款信息、消息、照片、音频、视频等。"</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"共享屏幕"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"卫星,连接质量良好"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"卫星,可连接"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"卫星紧急呼救"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"紧急呼叫或紧急求救"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"工作资料"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"并不适合所有用户"</string>
<string name="tuner_warning" msgid="1861736288458481650">"系统界面调节工具可让您以更多方式调整及定制 Android 界面。在日后推出的版本中,这些实验性功能可能会变更、失效或消失。操作时请务必谨慎。"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"收起图标"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"展开图标"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"或"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"返回手势"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"主屏幕手势"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"快捷操作按键"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index e8532be..359b3cc 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"<xliff:g id="APPNAME">%1$s</xliff:g> 和其他開啟的應用程式偵測到此螢幕截圖。"</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"新增至筆記"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"加入連結"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"螢幕錄影機"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"正在處理螢幕錄影內容"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示錄影畫面工作階段通知"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"螢幕保護程式"</string>
<string name="ethernet_label" msgid="2203544727007463351">"以太網"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"請勿騷擾"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"優先模式"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"藍牙"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"找不到配對的裝置"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"輕按即可連結或解除連結裝置"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"使用藍牙"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"已連接"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"音訊分享功能"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"輕按即可切換或分享音訊"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"已儲存"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"解除連結"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"啟動"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"開啟「設定」"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"其他裝置"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切換概覽"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"優先模式"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"完成"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"設定"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"開啟"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"在錄影或投放時,此功能的服務供應商可存取螢幕顯示或裝置播放的任何資料,當中包括密碼、付款資料、相片、訊息和播放的語音等資料。"</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"分享或錄影應用程式"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"要與「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」分享螢幕畫面嗎?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"分享一個應用程式"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"分享整個螢幕畫面"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"分享一個應用程式"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"分享整個螢幕畫面"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"當你分享整個螢幕畫面時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可看到你畫面上的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"當你分享應用程式時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可看到該應用程式中顯示或播放的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"分享螢幕畫面"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"衛星,連線質素好"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"衛星,可以連線"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"緊急衛星連接"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"緊急電話或 SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"工作設定檔"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"這只是測試版本,並不包含完整功能"</string>
<string name="tuner_warning" msgid="1861736288458481650">"使用者介面調諧器讓你以更多方法修改和自訂 Android 使用者介面。但請小心,這些實驗功能可能會在日後發佈時更改、分拆或消失。"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"收合圖示"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"展開圖示"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"或"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"返去手勢"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"主畫面手勢"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"快捷操作鍵"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index e049374..63b19d6b 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"「<xliff:g id="APPNAME">%1$s</xliff:g>」和其他開啟的應用程式偵測到這張螢幕截圖。"</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"新增至記事本"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"包含連結"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"螢幕錄影器"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"處理螢幕錄影內容"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示螢幕畫面錄製工作階段通知"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"螢幕保護程式"</string>
<string name="ethernet_label" msgid="2203544727007463351">"乙太網路"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"零打擾"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"優先模式"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"藍牙"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"找不到配對的裝置"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"輕觸即可連結/取消連結裝置"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"使用藍牙"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"已連線"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"音訊分享"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"輕觸即可切換或分享音訊"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"已儲存"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"取消連結"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"啟用"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"開啟「設定」"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"其他裝置"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切換總覽"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"優先模式"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"完成"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"設定"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"開啟"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"當你錄製或投放內容時,提供這項功能的服務將可存取畫面上顯示的任何資訊或裝置播放的任何內容,包括密碼、付款資料、相片、訊息和你播放的音訊等資訊。"</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"分享或錄製應用程式"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"要使用「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」分享畫面嗎?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"分享單一應用程式的畫面"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"分享整個畫面"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"分享單一應用程式的畫面"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"分享整個畫面"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"當你分享整個畫面時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可存取畫面上的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音內容等資訊。"</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"當你分享應用程式畫面時,「<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>」可存取該應用程式顯示或播放的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音內容等資訊。"</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"分享畫面"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"衛星,連線品質良好"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"衛星,可連線"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"緊急衛星連線"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"緊急電話或緊急求救"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"工作資料夾"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"有趣與否,見仁見智"</string>
<string name="tuner_warning" msgid="1861736288458481650">"系統使用者介面調整精靈可讓你透過其他方式,調整及自訂 Android 使用者介面。這些實驗性功能隨著版本更新可能會變更、損壞或消失,執行時請務必謹慎。"</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"收合圖示"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"展開圖示"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"或"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"返回手勢"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"主畫面手勢"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"快捷操作鍵"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index d85db55..048cb01 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -104,6 +104,7 @@
<string name="screenshot_detected_multiple_template" msgid="7644827792093819241">"I-<xliff:g id="APPNAME">%1$s</xliff:g> namanye ama-app avuliwe athole lesi sithombe-skrini."</string>
<string name="app_clips_save_add_to_note" msgid="3460200751278069445">"Engeza kunothi"</string>
<string name="backlinks_include_link" msgid="4562093591148248158">"Faka ilinki"</string>
+ <string name="backlinks_duplicate_label_format" msgid="558445128952827926">"<xliff:g id="APPNAME">%1$s</xliff:g> <xliff:g id="FREQUENCYCOUNT">(%2$d)</xliff:g>"</string>
<string name="screenrecord_title" msgid="4257171601439507792">"Okokuqopha iskrini"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Icubungula okokuqopha iskrini"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Isaziso esiqhubekayo seseshini yokurekhoda isikrini"</string>
@@ -291,7 +292,8 @@
<string name="start_dreams" msgid="9131802557946276718">"Isigciniskrini"</string>
<string name="ethernet_label" msgid="2203544727007463351">"I-Ethernet"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Ungaphazamisi"</string>
- <string name="quick_settings_modes_label" msgid="5407025818652750501">"Amamodi okubalulekile"</string>
+ <!-- no translation found for quick_settings_modes_label (879156359479504244) -->
+ <skip />
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"I-Bluetooth"</string>
<string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"Awekho amadivayisi abhanqiwe atholakalayo"</string>
<string name="quick_settings_bluetooth_tile_subtitle" msgid="212752719010829550">"Thepha ukuze uxhumae noma ungaxhumi idivaysi"</string>
@@ -300,6 +302,7 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Sebenzisa iBluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ixhunyiwe"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Ukwabelana Ngokuqoshiwe"</string>
+ <string name="quick_settings_bluetooth_device_audio_sharing_or_switch_active" msgid="3227408556754456024">"Thepha ukuze ushintshe noma wabelane ngokulalelwayo"</string>
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Ilondoloziwe"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"nqamula"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"yenza kusebenze"</string>
@@ -431,7 +434,8 @@
<string name="sensor_privacy_dialog_open_settings" msgid="5635865896053011859">"Vula Amasethingi"</string>
<string name="media_seamless_other_device" msgid="4654849800789196737">"Enye idivayisi"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Guqula ukubuka konke"</string>
- <string name="zen_modes_dialog_title" msgid="4159138230418567383">"Amamodi okubalulekile"</string>
+ <!-- no translation found for zen_modes_dialog_title (8854640808100096934) -->
+ <skip />
<string name="zen_modes_dialog_done" msgid="6654130880256438950">"Kwenziwe"</string>
<string name="zen_modes_dialog_settings" msgid="2310248023728936697">"Amasethingi"</string>
<string name="zen_mode_on" msgid="9085304934016242591">"Vuliwe"</string>
@@ -532,8 +536,12 @@
<string name="media_projection_sys_service_dialog_warning" msgid="2443872865267330320">"Isevisi enikezela ngalo msebenzi izothola ukufinyelela kulo lonke ulwazi olubonakalayo esikrinini sakho noma oludlalwa kusuka kudivayisi yakho ngenkathi urekhoda noma usakaza. Lokhu kubandakanya ulwazi olufana namaphasiwedi, imininingwane yenkokhelo, izithombe, imilayezo, nomsindo owudlalayo."</string>
<string name="screen_share_generic_app_selector_title" msgid="8331515850599218288">"Yabelana noma urekhode i-app"</string>
<string name="media_projection_entry_app_permission_dialog_title" msgid="4613857256721708062">"Yabelana ngesikrini sakho ne-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>?"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_single_app" msgid="6314402084788062644">"Yabelana nge-app eyodwa"</string>
- <string name="media_projection_entry_app_permission_dialog_option_text_entire_screen" msgid="7381488112332599632">"Yabelana ngesikrini sonke"</string>
+ <string name="screen_share_permission_dialog_option_single_app" msgid="2974054871681567314">"Yabelana nge-app eyodwa"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_single_app (2308901434964846084) -->
+ <skip />
+ <string name="screen_share_permission_dialog_option_entire_screen" msgid="4493174362775038997">"Yabelana ngesikrini sonke"</string>
+ <!-- no translation found for media_projection_entry_app_permission_dialog_option_text_entire_screen (5100078808078139706) -->
+ <skip />
<string name="media_projection_entry_app_permission_dialog_warning_entire_screen" msgid="5504288438067851086">"Uma wabelana ngesikrini sakho sonke, noma yini esesikrinini sakho ibonakala ku-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Ngakho-ke qaphela ngezinto ezifana namaphasiwedi, imininingwane yenkokhelo, imilayezo, izithombe, nomsindo nevidiyo."</string>
<string name="media_projection_entry_app_permission_dialog_warning_single_app" msgid="7094417930857938876">"Uma wabelana nge-app, noma yini eboniswayo noma edlalwayo kuleyo app ibonakala ku-<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>. Ngakho-ke qaphela ngezinto ezifana namaphasiwedi, imininingwane yenkokhelo, imilayezo, izithombe, nomsindo nevidiyo."</string>
<string name="media_projection_entry_app_permission_dialog_continue_entire_screen" msgid="1850848182344377579">"Yabelana ngesikrini"</string>
@@ -718,8 +726,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Isethelayithi, uxhumano oluhle"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Isethelayithi, uxhumano luyatholakala"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Isethelayithi yokuxhumana ngezimo eziphuthumayo"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Ikholi ephuthumayo noma i-SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Iphrofayela yomsebenzi"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Kuyajabulisa kwabanye kodwa hhayi bonke"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Isishuni se-UI sesistimu sikunika izindlela ezingeziwe zokuhlobisa nokwenza ngezifiso isixhumanisi sokubona se-Android. Lezi zici zesilingo zingashintsha, zephuke, noma zinyamalale ekukhishweni kwangakusasa. Qhubeka ngokuqaphela."</string>
@@ -1386,6 +1393,18 @@
<string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Goqa isithonjana"</string>
<string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Nweba isithonjana"</string>
<string name="shortcut_helper_key_combinations_or_separator" msgid="7082902112102125540">"noma"</string>
+ <!-- no translation found for launch_keyboard_tutorial_notification_title (8849933155160522519) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_tutorial_notification_content (2880339951512757918) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_title (2243780062772196901) -->
+ <skip />
+ <!-- no translation found for launch_touchpad_tutorial_notification_content (7931085031240753226) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_title (1940023776496198762) -->
+ <skip />
+ <!-- no translation found for launch_keyboard_touchpad_tutorial_notification_content (1780725168171929365) -->
+ <skip />
<string name="touchpad_tutorial_back_gesture_button" msgid="2746834288077265946">"Ukunyakazisa umzimba kwangemuva"</string>
<string name="touchpad_tutorial_home_gesture_button" msgid="7640544867625955304">"Ukunyakazisa umzimba kwasekhaya"</string>
<string name="touchpad_tutorial_action_key_button" msgid="3220074511852927267">"Inkinobho yokufinyelela"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 8cf0fb2..a375264 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -29,7 +29,7 @@
<color name="status_bar_icons_hover_color_dark">#38000000</color> <!-- 22% black -->
<!-- The dark background color behind the shade -->
- <color name="shade_scrim_background_dark">@*android:color/black</color>
+ <color name="shade_scrim_background_dark">@androidprv:color/system_under_surface_light</color>
<!-- The color of the background in the separated list of the Global Actions menu -->
<color name="global_actions_separated_background">#F5F5F5</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index e5750d2..e1808fa 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1751,6 +1751,7 @@
<!-- System UI Dialog -->
<dimen name="dialog_title_text_size">24sp</dimen>
+ <dimen name="dialog_button_side_margin">8dp</dimen>
<!-- Internet panel related dimensions -->
<dimen name="internet_dialog_list_max_height">662dp</dimen>
@@ -2001,10 +2002,10 @@
<!-- Shadow for dream overlay status bar complications -->
<dimen name="dream_overlay_status_bar_key_text_shadow_dx">0.5dp</dimen>
<dimen name="dream_overlay_status_bar_key_text_shadow_dy">0.5dp</dimen>
- <dimen name="dream_overlay_status_bar_key_text_shadow_radius">1dp</dimen>
+ <dimen name="dream_overlay_status_bar_key_text_shadow_radius">3dp</dimen>
<dimen name="dream_overlay_status_bar_ambient_text_shadow_dx">0.5dp</dimen>
<dimen name="dream_overlay_status_bar_ambient_text_shadow_dy">0.5dp</dimen>
- <dimen name="dream_overlay_status_bar_ambient_text_shadow_radius">2dp</dimen>
+ <dimen name="dream_overlay_status_bar_ambient_text_shadow_radius">3dp</dimen>
<dimen name="dream_overlay_icon_inset_dimen">0dp</dimen>
<!-- Default device corner radius, used for assist UI -->
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d3d757b..1fb1dad 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -269,8 +269,12 @@
<string name="screenshot_detected_multiple_template"><xliff:g id="appName" example="Google Chrome">%1$s</xliff:g> and other open apps detected this screenshot.</string>
<!-- Add to note button used in App Clips flow to return the saved screenshot image to notes app. [CHAR LIMIT=NONE] -->
<string name="app_clips_save_add_to_note">Add to note</string>
+ <!-- A check box used in App Clips flow to return the captured backlink of the screenshotted app to notes app. [CHAR LIMIT=NONE] -->
<string name="backlinks_include_link">Include link</string>
+ <!-- A label for backlinks app that is used if there are multiple backlinks with same app name. [CHAR LIMIT=NONE] -->
<string name="backlinks_duplicate_label_format"><xliff:g id="appName" example="Google Chrome">%1$s</xliff:g> <xliff:g id="frequencyCount" example="(1)">(%2$d)</xliff:g></string>
+ <!-- An error message to inform user that capturing backlink from cross profile apps is not possible. [CHAR LIMIT=NONE] -->
+ <string name="backlinks_cross_profile_error">Links can\'t be added from other profiles</string>
<!-- Notification title displayed for screen recording [CHAR LIMIT=50]-->
<string name="screenrecord_title">Screen Recorder</string>
@@ -3699,6 +3703,22 @@
-->
<string name="shortcut_helper_key_combinations_or_separator">or</string>
+ <!-- Keyboard touchpad tutorial scheduler-->
+ <!-- Notification title for launching keyboard tutorial [CHAR_LIMIT=100] -->
+ <string name="launch_keyboard_tutorial_notification_title">Navigate using your keyboard</string>
+ <!-- Notification text for launching keyboard tutorial [CHAR_LIMIT=100] -->
+ <string name="launch_keyboard_tutorial_notification_content">Learn keyboards shortcuts</string>
+
+ <!-- Notification title for launching touchpad tutorial [CHAR_LIMIT=100] -->
+ <string name="launch_touchpad_tutorial_notification_title">Navigate using your touchpad</string>
+ <!-- Notification text for launching keyboard tutorial [CHAR_LIMIT=100] -->
+ <string name="launch_touchpad_tutorial_notification_content">Learn touchpad gestures</string>
+
+ <!-- Notification title for launching keyboard tutorial [CHAR_LIMIT=100] -->
+ <string name="launch_keyboard_touchpad_tutorial_notification_title">Navigate using your keyboard and touchpad</string>
+ <!-- Notification text for launching keyboard tutorial [CHAR_LIMIT=100] -->
+ <string name="launch_keyboard_touchpad_tutorial_notification_content">Learn touchpad gestures, keyboards shortcuts, and more</string>
+
<!-- TOUCHPAD TUTORIAL-->
<!-- Label for button opening tutorial for back gesture on touchpad [CHAR LIMIT=NONE] -->
<string name="touchpad_tutorial_back_gesture_button">Back gesture</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 3ef6243..a02c354 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -505,14 +505,14 @@
<item name="onSurfaceVariant">?androidprv:attr/materialColorOnSurfaceVariant</item>
<item name="outline">?androidprv:attr/materialColorOutline</item>
- <item name="shadeActive">@color/material_dynamic_primary90</item>
- <item name="onShadeActive">@color/material_dynamic_primary10</item>
- <item name="onShadeActiveVariant">@color/material_dynamic_primary30</item>
- <item name="shadeInactive">@color/material_dynamic_neutral20</item>
- <item name="onShadeInactive">@color/material_dynamic_neutral90</item>
- <item name="onShadeInactiveVariant">@color/material_dynamic_neutral_variant80</item>
- <item name="shadeDisabled">@color/shade_disabled</item>
- <item name="underSurface">@color/material_dynamic_neutral0</item>
+ <item name="shadeActive">?androidprv:attr/customColorShadeActive</item>
+ <item name="onShadeActive">?androidprv:attr/customColorOnShadeActive</item>
+ <item name="onShadeActiveVariant">?androidprv:attr/customColorOnShadeActiveVariant</item>
+ <item name="shadeInactive">?androidprv:attr/customColorShadeInactive</item>
+ <item name="onShadeInactive">?androidprv:attr/customColorOnShadeInactive</item>
+ <item name="onShadeInactiveVariant">?androidprv:attr/customColorOnShadeInactiveVariant</item>
+ <item name="shadeDisabled">?androidprv:attr/customColorShadeDisabled</item>
+ <item name="underSurface">?androidprv:attr/customColorUnderSurface</item>
<item name="android:itemTextAppearance">@style/Control.MenuItem</item>
</style>
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
index 7733841..5e36539 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
@@ -17,6 +17,7 @@
package com.android.keyguard;
import static com.android.systemui.DejankUtils.whitelistIpcs;
+import static com.android.systemui.Flags.msdlFeedback;
import android.annotation.SuppressLint;
import android.app.ActivityOptions;
@@ -46,6 +47,9 @@
import com.android.systemui.util.EmergencyDialerConstants;
import com.android.systemui.util.ViewController;
+import com.google.android.msdl.data.model.MSDLToken;
+import com.google.android.msdl.domain.MSDLPlayer;
+
import java.util.concurrent.Executor;
import javax.inject.Inject;
@@ -67,6 +71,7 @@
private final Executor mMainExecutor;
private final Executor mBackgroundExecutor;
private final SelectedUserInteractor mSelectedUserInteractor;
+ private final MSDLPlayer mMSDLPlayer;
private final KeyguardUpdateMonitorCallback mInfoCallback =
new KeyguardUpdateMonitorCallback() {
@@ -99,7 +104,8 @@
MetricsLogger metricsLogger,
LockPatternUtils lockPatternUtils,
Executor mainExecutor, Executor backgroundExecutor,
- SelectedUserInteractor selectedUserInteractor) {
+ SelectedUserInteractor selectedUserInteractor,
+ MSDLPlayer msdlPlayer) {
super(view);
mConfigurationController = configurationController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -112,6 +118,7 @@
mMainExecutor = mainExecutor;
mBackgroundExecutor = backgroundExecutor;
mSelectedUserInteractor = selectedUserInteractor;
+ mMSDLPlayer = msdlPlayer;
}
@Override
@@ -165,6 +172,9 @@
@SuppressLint("MissingPermission")
public void takeEmergencyCallAction() {
mMetricsLogger.action(MetricsEvent.ACTION_EMERGENCY_CALL);
+ if (msdlFeedback()) {
+ mMSDLPlayer.playToken(MSDLToken.KEYPRESS_RETURN, null);
+ }
if (mPowerManager != null) {
mPowerManager.userActivity(SystemClock.uptimeMillis(), true);
}
@@ -221,6 +231,7 @@
private final Executor mMainExecutor;
private final Executor mBackgroundExecutor;
private final SelectedUserInteractor mSelectedUserInteractor;
+ private final MSDLPlayer mMSDLPlayer;
@Inject
public Factory(ConfigurationController configurationController,
@@ -233,7 +244,8 @@
LockPatternUtils lockPatternUtils,
@Main Executor mainExecutor,
@Background Executor backgroundExecutor,
- SelectedUserInteractor selectedUserInteractor) {
+ SelectedUserInteractor selectedUserInteractor,
+ MSDLPlayer msdlPlayer) {
mConfigurationController = configurationController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -246,6 +258,7 @@
mMainExecutor = mainExecutor;
mBackgroundExecutor = backgroundExecutor;
mSelectedUserInteractor = selectedUserInteractor;
+ mMSDLPlayer = msdlPlayer;
}
/** Construct an {@link com.android.keyguard.EmergencyButtonController}. */
@@ -253,7 +266,7 @@
return new EmergencyButtonController(view, mConfigurationController,
mKeyguardUpdateMonitor, mPowerManager, mActivityTaskManager, mShadeController,
mTelecomManager, mMetricsLogger, mLockPatternUtils, mMainExecutor,
- mBackgroundExecutor, mSelectedUserInteractor);
+ mBackgroundExecutor, mSelectedUserInteractor, mMSDLPlayer);
}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
index dd84bc6..92e5432 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
@@ -271,7 +271,8 @@
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
keyguardSecurityCallback, mLatencyTracker, mFalsingCollector,
emergencyButtonController, mMessageAreaControllerFactory,
- mDevicePostureController, mFeatureFlags, mSelectedUserInteractor);
+ mDevicePostureController, mFeatureFlags, mSelectedUserInteractor,
+ mMSDLPlayer);
} else if (keyguardInputView instanceof KeyguardPasswordView) {
return new KeyguardPasswordViewController((KeyguardPasswordView) keyguardInputView,
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
index caa74780..f74d93e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
@@ -36,6 +36,7 @@
import com.android.internal.widget.LockscreenCredential;
import com.android.keyguard.EmergencyButtonController.EmergencyButtonCallback;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.systemui.bouncer.ui.helper.BouncerHapticHelper;
import com.android.systemui.classifier.FalsingClassifier;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags;
@@ -43,6 +44,8 @@
import com.android.systemui.statusbar.policy.DevicePostureController;
import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
+import com.google.android.msdl.domain.MSDLPlayer;
+
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -67,6 +70,7 @@
private LockPatternView mLockPatternView;
private CountDownTimer mCountdownTimer;
private AsyncTask<?, ?, ?> mPendingLockCheck;
+ private MSDLPlayer mMSDLPlayer;
private EmergencyButtonCallback mEmergencyButtonCallback = new EmergencyButtonCallback() {
@Override
@@ -75,6 +79,10 @@
}
};
+ private final LockPatternView.ExternalHapticsPlayer mExternalHapticsPlayer = () -> {
+ BouncerHapticHelper.INSTANCE.playPatternDotFeedback(mMSDLPlayer, mView);
+ };
+
/**
* Useful for clearing out the wrong pattern after a delay
*/
@@ -166,6 +174,10 @@
boolean isValidPattern) {
boolean dismissKeyguard = mSelectedUserInteractor.getSelectedUserId() == userId;
if (matched) {
+ BouncerHapticHelper.INSTANCE.playMSDLAuthenticationFeedback(
+ /* authenticationSucceeded= */true,
+ /* player =*/mMSDLPlayer
+ );
getKeyguardSecurityCallback().reportUnlockAttempt(userId, true, 0);
if (dismissKeyguard) {
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
@@ -173,6 +185,10 @@
getKeyguardSecurityCallback().dismiss(true, userId, SecurityMode.Pattern);
}
} else {
+ BouncerHapticHelper.INSTANCE.playMSDLAuthenticationFeedback(
+ /* authenticationSucceeded= */false,
+ /* player =*/mMSDLPlayer
+ );
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
if (isValidPattern) {
getKeyguardSecurityCallback().reportUnlockAttempt(userId, false, timeoutMs);
@@ -200,7 +216,7 @@
EmergencyButtonController emergencyButtonController,
KeyguardMessageAreaController.Factory messageAreaControllerFactory,
DevicePostureController postureController, FeatureFlags featureFlags,
- SelectedUserInteractor selectedUserInteractor) {
+ SelectedUserInteractor selectedUserInteractor, MSDLPlayer msdlPlayer) {
super(view, securityMode, keyguardSecurityCallback, emergencyButtonController,
messageAreaControllerFactory, featureFlags, selectedUserInteractor);
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -212,6 +228,7 @@
featureFlags.isEnabled(LOCKSCREEN_ENABLE_LANDSCAPE));
mLockPatternView = mView.findViewById(R.id.lockPatternView);
mPostureController = postureController;
+ mMSDLPlayer = msdlPlayer;
}
@Override
@@ -249,6 +266,7 @@
if (deadline != 0) {
handleAttemptLockout(deadline);
}
+ mLockPatternView.setExternalHapticsPlayer(mExternalHapticsPlayer);
}
@Override
@@ -262,6 +280,7 @@
cancelBtn.setOnClickListener(null);
}
mPostureController.removeCallback(mPostureCallback);
+ mLockPatternView.setExternalHapticsPlayer(null);
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 61f9800..2d28a18 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -35,7 +35,6 @@
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
-import android.app.admin.flags.Flags;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
@@ -1140,12 +1139,7 @@
int remainingBeforeWipe, int failedAttempts) {
int userType = USER_TYPE_PRIMARY;
if (expiringUserId == userId) {
- int primaryUser = UserHandle.USER_SYSTEM;
- if (Flags.headlessSingleUserFixes()) {
- if (mainUserId != null) {
- primaryUser = mainUserId;
- }
- }
+ int primaryUser = mainUserId != null ? mainUserId : UserHandle.USER_SYSTEM;
// TODO: http://b/23522538
if (expiringUserId != primaryUser) {
userType = USER_TYPE_SECONDARY_USER;
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardQuickAffordancesLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardQuickAffordancesLogger.kt
index c11cf55..7dbf013 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardQuickAffordancesLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardQuickAffordancesLogger.kt
@@ -16,6 +16,7 @@
package com.android.keyguard.logging
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordanceViewModel
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
import com.android.systemui.log.dagger.KeyguardQuickAffordancesLog
@@ -63,6 +64,15 @@
)
}
+ fun logUpdate(viewModel: KeyguardQuickAffordanceViewModel) {
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ { str1 = viewModel.toString() },
+ { "QuickAffordance updated: $str1" }
+ )
+ }
+
private fun String.decode(): Pair<String, String> {
val splitUp = this.split(DELIMITER)
return Pair(splitUp[0], splitUp[1])
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MirrorWindowControl.java b/packages/SystemUI/src/com/android/systemui/accessibility/MirrorWindowControl.java
index 443441f..eb4de68 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/MirrorWindowControl.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/MirrorWindowControl.java
@@ -18,6 +18,9 @@
import static android.view.WindowManager.LayoutParams;
+import static com.android.app.viewcapture.ViewCaptureFactory.getViewCaptureAwareWindowManagerInstance;
+import static com.android.systemui.Flags.enableViewCaptureTracing;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -29,8 +32,8 @@
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.WindowManager;
+import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
import com.android.systemui.res.R;
/**
@@ -70,11 +73,12 @@
* @see #setDefaultPosition(LayoutParams)
*/
private final Point mControlPosition = new Point();
- private final WindowManager mWindowManager;
+ private final ViewCaptureAwareWindowManager mWindowManager;
MirrorWindowControl(Context context) {
mContext = context;
- mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+ mWindowManager = getViewCaptureAwareWindowManagerInstance(mContext,
+ enableViewCaptureTracing());
}
public void setWindowDelegate(@Nullable MirrorWindowDelegate windowDelegate) {
diff --git a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java b/packages/SystemUI/src/com/android/systemui/accessibility/data/model/CaptioningModel.kt
similarity index 71%
copy from services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
copy to packages/SystemUI/src/com/android/systemui/accessibility/data/model/CaptioningModel.kt
index 502337c..4eb2274 100644
--- a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/data/model/CaptioningModel.kt
@@ -14,11 +14,9 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.systemui.accessibility.data.model
-class BinaryStatePowerStatsLayout extends EnergyConsumerPowerStatsLayout {
- BinaryStatePowerStatsLayout() {
- addDeviceSectionUsageDuration();
- addUidSectionUsageDuration();
- }
-}
+data class CaptioningModel(
+ val isSystemAudioCaptioningUiEnabled: Boolean,
+ val isSystemAudioCaptioningEnabled: Boolean,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/CaptioningRepository.kt b/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/CaptioningRepository.kt
new file mode 100644
index 0000000..5414b62
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/CaptioningRepository.kt
@@ -0,0 +1,105 @@
+/*
+ * 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.accessibility.data.repository
+
+import android.annotation.SuppressLint
+import android.view.accessibility.CaptioningManager
+import com.android.systemui.accessibility.data.model.CaptioningModel
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.user.data.repository.UserRepository
+import com.android.systemui.user.utils.UserScopedService
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
+import javax.inject.Inject
+import kotlin.coroutines.CoroutineContext
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.withContext
+
+interface CaptioningRepository {
+
+ /** Current state of Live Captions. */
+ val captioningModel: StateFlow<CaptioningModel?>
+
+ /** Sets [CaptioningModel.isSystemAudioCaptioningEnabled]. */
+ suspend fun setIsSystemAudioCaptioningEnabled(isEnabled: Boolean)
+}
+
+@OptIn(ExperimentalCoroutinesApi::class)
+class CaptioningRepositoryImpl
+@Inject
+constructor(
+ private val userScopedCaptioningManagerProvider: UserScopedService<CaptioningManager>,
+ userRepository: UserRepository,
+ @Background private val backgroundCoroutineContext: CoroutineContext,
+ @Application coroutineScope: CoroutineScope,
+) : CaptioningRepository {
+
+ @SuppressLint("NonInjectedService") // this uses user-aware context
+ private val captioningManager: StateFlow<CaptioningManager?> =
+ userRepository.selectedUser
+ .map { userScopedCaptioningManagerProvider.forUser(it.userInfo.userHandle) }
+ .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), null)
+
+ override val captioningModel: StateFlow<CaptioningModel?> =
+ captioningManager
+ .filterNotNull()
+ .flatMapLatest { it.captioningModel() }
+ .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), null)
+
+ override suspend fun setIsSystemAudioCaptioningEnabled(isEnabled: Boolean) {
+ withContext(backgroundCoroutineContext) {
+ captioningManager.value?.isSystemAudioCaptioningEnabled = isEnabled
+ }
+ }
+
+ private fun CaptioningManager.captioningModel(): Flow<CaptioningModel> {
+ return conflatedCallbackFlow {
+ val listener =
+ object : CaptioningManager.CaptioningChangeListener() {
+
+ override fun onSystemAudioCaptioningChanged(enabled: Boolean) {
+ trySend(Unit)
+ }
+
+ override fun onSystemAudioCaptioningUiChanged(enabled: Boolean) {
+ trySend(Unit)
+ }
+ }
+ addCaptioningChangeListener(listener)
+ awaitClose { removeCaptioningChangeListener(listener) }
+ }
+ .onStart { emit(Unit) }
+ .map {
+ CaptioningModel(
+ isSystemAudioCaptioningEnabled = isSystemAudioCaptioningEnabled,
+ isSystemAudioCaptioningUiEnabled = isSystemAudioCaptioningUiEnabled,
+ )
+ }
+ .flowOn(backgroundCoroutineContext)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/domain/interactor/CaptioningInteractor.kt b/packages/SystemUI/src/com/android/systemui/accessibility/domain/interactor/CaptioningInteractor.kt
new file mode 100644
index 0000000..840edf4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/domain/interactor/CaptioningInteractor.kt
@@ -0,0 +1,38 @@
+/*
+ * 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.accessibility.domain.interactor
+
+import com.android.systemui.accessibility.data.repository.CaptioningRepository
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.map
+
+@SysUISingleton
+class CaptioningInteractor @Inject constructor(private val repository: CaptioningRepository) {
+
+ val isSystemAudioCaptioningEnabled: Flow<Boolean> =
+ repository.captioningModel.filterNotNull().map { it.isSystemAudioCaptioningEnabled }
+
+ val isSystemAudioCaptioningUiEnabled: Flow<Boolean> =
+ repository.captioningModel.filterNotNull().map { it.isSystemAudioCaptioningUiEnabled }
+
+ suspend fun setIsSystemAudioCaptioningEnabled(enabled: Boolean) {
+ repository.setIsSystemAudioCaptioningEnabled(enabled)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java
index d08653c3..60edaae 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java
@@ -52,7 +52,6 @@
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
-import com.android.internal.logging.UiEventLogger;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.HapClientProfile;
@@ -105,7 +104,8 @@
private final AudioManager mAudioManager;
private final LocalBluetoothProfileManager mProfileManager;
private final HapClientProfile mHapClientProfile;
- private final UiEventLogger mUiEventLogger;
+ private final HearingDevicesUiEventLogger mUiEventLogger;
+ private final int mLaunchSourceId;
private HearingDevicesListAdapter mDeviceListAdapter;
private HearingDevicesPresetsController mPresetsController;
private Context mApplicationContext;
@@ -153,20 +153,22 @@
public interface Factory {
/** Create a {@link HearingDevicesDialogDelegate} instance */
HearingDevicesDialogDelegate create(
- boolean showPairNewDevice);
+ boolean showPairNewDevice,
+ @HearingDevicesUiEventLogger.LaunchSourceId int launchSource);
}
@AssistedInject
public HearingDevicesDialogDelegate(
@Application Context applicationContext,
@Assisted boolean showPairNewDevice,
+ @Assisted @HearingDevicesUiEventLogger.LaunchSourceId int launchSourceId,
SystemUIDialog.Factory systemUIDialogFactory,
ActivityStarter activityStarter,
DialogTransitionAnimator dialogTransitionAnimator,
@Nullable LocalBluetoothManager localBluetoothManager,
@Main Handler handler,
AudioManager audioManager,
- UiEventLogger uiEventLogger) {
+ HearingDevicesUiEventLogger uiEventLogger) {
mApplicationContext = applicationContext;
mShowPairNewDevice = showPairNewDevice;
mSystemUIDialogFactory = systemUIDialogFactory;
@@ -178,6 +180,7 @@
mProfileManager = localBluetoothManager.getProfileManager();
mHapClientProfile = mProfileManager.getHapClientProfile();
mUiEventLogger = uiEventLogger;
+ mLaunchSourceId = launchSourceId;
}
@Override
@@ -191,7 +194,7 @@
@Override
public void onDeviceItemGearClicked(@NonNull DeviceItem deviceItem, @NonNull View view) {
- mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_GEAR_CLICK);
+ mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_GEAR_CLICK, mLaunchSourceId);
dismissDialogIfExists();
Intent intent = new Intent(ACTION_BLUETOOTH_DEVICE_DETAILS);
Bundle bundle = new Bundle();
@@ -207,15 +210,17 @@
CachedBluetoothDevice cachedBluetoothDevice = deviceItem.getCachedBluetoothDevice();
switch (deviceItem.getType()) {
case ACTIVE_MEDIA_BLUETOOTH_DEVICE, CONNECTED_BLUETOOTH_DEVICE -> {
- mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_DISCONNECT);
+ mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_DISCONNECT,
+ mLaunchSourceId);
cachedBluetoothDevice.disconnect();
}
case AVAILABLE_MEDIA_BLUETOOTH_DEVICE -> {
- mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_SET_ACTIVE);
+ mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_SET_ACTIVE,
+ mLaunchSourceId);
cachedBluetoothDevice.setActive();
}
case SAVED_BLUETOOTH_DEVICE -> {
- mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_CONNECT);
+ mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_CONNECT, mLaunchSourceId);
cachedBluetoothDevice.connect();
}
}
@@ -275,7 +280,7 @@
if (mLocalBluetoothManager == null) {
return;
}
- mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_DIALOG_SHOW);
+ mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_DIALOG_SHOW, mLaunchSourceId);
mPairButton = dialog.requireViewById(R.id.pair_new_device_button);
mDeviceList = dialog.requireViewById(R.id.device_list);
mPresetSpinner = dialog.requireViewById(R.id.preset_spinner);
@@ -363,7 +368,8 @@
mPresetSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_PRESET_SELECT);
+ mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_PRESET_SELECT,
+ mLaunchSourceId);
mPresetsController.selectPreset(
mPresetsController.getAllPresetInfo().get(position).getIndex());
}
@@ -381,7 +387,7 @@
private void setupPairNewDeviceButton(SystemUIDialog dialog, @Visibility int visibility) {
if (visibility == VISIBLE) {
mPairButton.setOnClickListener(v -> {
- mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_PAIR);
+ mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_PAIR, mLaunchSourceId);
dismissDialogIfExists();
final Intent intent = new Intent(Settings.ACTION_HEARING_DEVICE_PAIRING_SETTINGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
@@ -485,7 +491,8 @@
final String name = intent.getComponent() != null
? intent.getComponent().flattenToString()
: intent.getPackage() + "/" + intent.getAction();
- mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_RELATED_TOOL_CLICK, 0, name);
+ mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_RELATED_TOOL_CLICK,
+ mLaunchSourceId, name);
dismissDialogIfExists();
mActivityStarter.postStartActivityDismissingKeyguard(intent, /* delay= */ 0,
mDialogTransitionAnimator.createActivityTransitionController(view));
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManager.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManager.java
index bc4cb45..3d24177 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManager.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogManager.java
@@ -70,8 +70,10 @@
* Shows the dialog.
*
* @param expandable {@link Expandable} from which the dialog is shown.
+ * @param launchSourceId the id indicates where the dialog is launched from.
*/
- public void showDialog(Expandable expandable) {
+ public void showDialog(Expandable expandable,
+ @HearingDevicesUiEventLogger.LaunchSourceId int launchSourceId) {
if (mDialog != null) {
if (DEBUG) {
Log.d(TAG, "HearingDevicesDialog already showing. Destroy it first.");
@@ -91,7 +93,8 @@
});
pairedHearingDeviceCheckTask.addListener(() -> {
try {
- mDialog = mDialogFactory.create(!pairedHearingDeviceCheckTask.get()).createDialog();
+ mDialog = mDialogFactory.create(!pairedHearingDeviceCheckTask.get(),
+ launchSourceId).createDialog();
if (expandable != null) {
DialogTransitionAnimator.Controller controller =
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogReceiver.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogReceiver.java
index 6a34d19..02e65fd 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogReceiver.java
@@ -16,6 +16,8 @@
package com.android.systemui.accessibility.hearingaid;
+import static com.android.systemui.accessibility.hearingaid.HearingDevicesUiEventLogger.LAUNCH_SOURCE_A11Y;
+
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -46,7 +48,7 @@
}
if (ACTION.equals(intent.getAction())) {
- mDialogManager.showDialog(/* view= */ null);
+ mDialogManager.showDialog(/* expandable= */ null, LAUNCH_SOURCE_A11Y);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.java
deleted file mode 100644
index 3fbe56e..0000000
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.java
+++ /dev/null
@@ -1,51 +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.systemui.accessibility.hearingaid;
-
-import com.android.internal.logging.UiEvent;
-import com.android.internal.logging.UiEventLogger;
-
-public enum HearingDevicesUiEvent implements UiEventLogger.UiEventEnum {
-
- @UiEvent(doc = "Hearing devices dialog is shown")
- HEARING_DEVICES_DIALOG_SHOW(1848),
- @UiEvent(doc = "Pair new device")
- HEARING_DEVICES_PAIR(1849),
- @UiEvent(doc = "Connect to the device")
- HEARING_DEVICES_CONNECT(1850),
- @UiEvent(doc = "Disconnect from the device")
- HEARING_DEVICES_DISCONNECT(1851),
- @UiEvent(doc = "Set the device as active device")
- HEARING_DEVICES_SET_ACTIVE(1852),
- @UiEvent(doc = "Click on the device gear to enter device detail page")
- HEARING_DEVICES_GEAR_CLICK(1853),
- @UiEvent(doc = "Select a preset from preset spinner")
- HEARING_DEVICES_PRESET_SELECT(1854),
- @UiEvent(doc = "Click on related tool")
- HEARING_DEVICES_RELATED_TOOL_CLICK(1856);
-
- private final int mId;
-
- HearingDevicesUiEvent(int id) {
- mId = id;
- }
-
- @Override
- public int getId() {
- return mId;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.kt b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.kt
new file mode 100644
index 0000000..9e77b02
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEvent.kt
@@ -0,0 +1,35 @@
+/*
+ * 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.accessibility.hearingaid
+
+import com.android.internal.logging.UiEvent
+import com.android.internal.logging.UiEventLogger
+
+enum class HearingDevicesUiEvent(private val id: Int) : UiEventLogger.UiEventEnum {
+
+ @UiEvent(doc = "Hearing devices dialog is shown") HEARING_DEVICES_DIALOG_SHOW(1848),
+ @UiEvent(doc = "Pair new device") HEARING_DEVICES_PAIR(1849),
+ @UiEvent(doc = "Connect to the device") HEARING_DEVICES_CONNECT(1850),
+ @UiEvent(doc = "Disconnect from the device") HEARING_DEVICES_DISCONNECT(1851),
+ @UiEvent(doc = "Set the device as active device") HEARING_DEVICES_SET_ACTIVE(1852),
+ @UiEvent(doc = "Click on the device gear to enter device detail page")
+ HEARING_DEVICES_GEAR_CLICK(1853),
+ @UiEvent(doc = "Select a preset from preset spinner") HEARING_DEVICES_PRESET_SELECT(1854),
+ @UiEvent(doc = "Click on related tool") HEARING_DEVICES_RELATED_TOOL_CLICK(1856);
+
+ override fun getId(): Int = this.id
+}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEventLogger.kt b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEventLogger.kt
new file mode 100644
index 0000000..0b32cfc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesUiEventLogger.kt
@@ -0,0 +1,49 @@
+/*
+ * 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.accessibility.hearingaid
+
+import android.annotation.IntDef
+import com.android.internal.logging.UiEventLogger
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+
+@SysUISingleton
+class HearingDevicesUiEventLogger @Inject constructor(private val uiEventLogger: UiEventLogger) {
+
+ /** Logs the given event */
+ fun log(event: UiEventLogger.UiEventEnum, launchSourceId: Int) {
+ log(event, launchSourceId, null)
+ }
+
+ fun log(event: UiEventLogger.UiEventEnum, launchSourceId: Int, pkgName: String?) {
+ uiEventLogger.log(event, launchSourceId, pkgName)
+ }
+
+ /**
+ * The possible launch source of hearing devices dialog
+ *
+ * @hide
+ */
+ @IntDef(LAUNCH_SOURCE_UNKNOWN, LAUNCH_SOURCE_A11Y, LAUNCH_SOURCE_QS_TILE)
+ annotation class LaunchSourceId
+
+ companion object {
+ const val LAUNCH_SOURCE_UNKNOWN = 0
+ const val LAUNCH_SOURCE_A11Y = 1 // launch from AccessibilityManagerService
+ const val LAUNCH_SOURCE_QS_TILE = 2
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt b/packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt
index b0314d8..476d54b 100644
--- a/packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt
@@ -32,5 +32,6 @@
interface AmbientModule {
companion object {
const val TOUCH_HANDLERS = "touch_handlers"
+ const val LOGGING_NAME = "logging_name"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java
index 1be6f9e..0898134 100644
--- a/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java
@@ -18,6 +18,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+import static com.android.systemui.ambient.dagger.AmbientModule.LOGGING_NAME;
import static com.android.systemui.shared.Flags.bouncerAreaExclusion;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
@@ -44,6 +45,9 @@
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.DisplayId;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.log.LogBuffer;
+import com.android.systemui.log.core.Logger;
+import com.android.systemui.log.dagger.CommunalTouchLog;
import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.util.display.DisplayHelper;
@@ -62,6 +66,8 @@
import java.util.stream.Collectors;
import javax.inject.Inject;
+import javax.inject.Named;
+
/**
* {@link TouchMonitor} is responsible for monitoring touches and gestures over the
@@ -73,6 +79,7 @@
// This executor is used to protect {@code mActiveTouchSessions} from being modified
// concurrently. Any operation that adds or removes values should use this executor.
public String TAG = "DreamOverlayTouchMonitor";
+ private final Logger mLogger;
private final Executor mMainExecutor;
private final Executor mBackgroundExecutor;
@@ -116,6 +123,11 @@
TouchSessionImpl touchSessionImpl) {
return CallbackToFutureAdapter.getFuture(completer -> {
mMainExecutor.execute(() -> {
+ mLogger.i(msg -> "Session popped, hashCode: " + msg.getInt1(), msg -> {
+ msg.setInt1(touchSessionImpl.hashCode());
+ return kotlin.Unit.INSTANCE;
+ });
+
if (mActiveTouchSessions.remove(touchSessionImpl)) {
touchSessionImpl.onRemoved();
@@ -269,6 +281,7 @@
* When invoked, instantiates a new {@link InputSession} to monitor touch events.
*/
private void startMonitoring() {
+ mLogger.i("startMonitoring(): monitoring started");
stopMonitoring(true);
if (bouncerAreaExclusion()) {
@@ -322,6 +335,12 @@
}
if (!mActiveTouchSessions.isEmpty() && !force) {
+ mLogger.i(msg -> "stopMonitoring(): waiting for sessions to end: " + msg.getStr1(),
+ msg -> {
+ msg.setStr1(mActiveTouchSessions.stream().map(Object::hashCode).map(
+ Object::toString).collect(Collectors.joining(",")));
+ return kotlin.Unit.INSTANCE;
+ });
mStopMonitoringPending = true;
return;
}
@@ -341,6 +360,8 @@
mCurrentInputSession.dispose();
mCurrentInputSession = null;
mStopMonitoringPending = false;
+
+ mLogger.i("stopMonitoring(): monitoring finished");
}
@@ -405,12 +426,29 @@
// created so the
// final session is correct.
sessionMap.forEach((dreamTouchHandler, touchSession)
- -> dreamTouchHandler.onSessionStart(touchSession));
+ -> {
+ if (ev instanceof MotionEvent motionEvent) {
+ int x = Math.round(motionEvent.getX());
+ int y = Math.round(motionEvent.getY());
+ mLogger.i(
+ msg -> "Session start, handler: " + msg.getStr1() + ", x: "
+ + msg.getLong1() + ", y: " + msg.getLong2()
+ + ", hashCode: " + msg.getInt1(), msg -> {
+ msg.setStr1(
+ dreamTouchHandler.getClass().getSimpleName());
+ msg.setLong1(x);
+ msg.setLong2(y);
+ msg.setInt1(touchSession.hashCode());
+ return kotlin.Unit.INSTANCE;
+ });
+ }
+ dreamTouchHandler.onSessionStart(touchSession);
+ });
}
// Find active sessions and invoke on InputEvent.
mActiveTouchSessions.stream()
- .map(touchSessionStack -> touchSessionStack.getEventListeners())
+ .map(TouchSessionImpl::getEventListeners)
.flatMap(Collection::stream)
.forEach(inputEventListener -> inputEventListener.onInputEvent(ev));
}
@@ -526,6 +564,8 @@
* returned.
* @param handlers This set represents the {@link TouchHandler} instances that will
* participate in touch handling.
+ * @param loggingName Identifying string for this {@link TouchMonitor} that will be used
+ * when logging to {@link CommunalTouchLog}.
*/
@Inject
public TouchMonitor(
@@ -537,7 +577,9 @@
ConfigurationInteractor configurationInteractor,
Set<TouchHandler> handlers,
IWindowManager windowManagerService,
- @DisplayId int displayId) {
+ @DisplayId int displayId,
+ @Named(LOGGING_NAME) String loggingName,
+ @CommunalTouchLog LogBuffer logBuffer) {
mDisplayId = displayId;
mHandlers = handlers;
mInputSessionFactory = inputSessionFactory;
@@ -547,6 +589,7 @@
mDisplayHelper = displayHelper;
mWindowManagerService = windowManagerService;
mConfigurationInteractor = configurationInteractor;
+ mLogger = new Logger(logBuffer, loggingName + ":TouchMonitor");
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchComponent.kt b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchComponent.kt
index 390e53b..ba552c3 100644
--- a/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchComponent.kt
@@ -16,6 +16,7 @@
package com.android.systemui.ambient.touch.dagger
import androidx.lifecycle.LifecycleOwner
+import com.android.systemui.ambient.dagger.AmbientModule.Companion.LOGGING_NAME
import com.android.systemui.ambient.dagger.AmbientModule.Companion.TOUCH_HANDLERS
import com.android.systemui.ambient.touch.TouchHandler
import com.android.systemui.ambient.touch.TouchMonitor
@@ -36,7 +37,8 @@
@BindsInstance lifecycleOwner: LifecycleOwner,
@BindsInstance
@Named(TOUCH_HANDLERS)
- touchHandlers: Set<@JvmSuppressWildcards TouchHandler>
+ touchHandlers: Set<@JvmSuppressWildcards TouchHandler>,
+ @BindsInstance @Named(LOGGING_NAME) loggingName: String,
): AmbientTouchComponent
}
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
index fcba425..3080e19 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
@@ -16,7 +16,6 @@
package com.android.systemui.authentication.domain.interactor
-import android.app.admin.flags.Flags
import android.os.UserHandle
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockPatternView
@@ -289,12 +288,7 @@
private suspend fun getWipeTarget(): WipeTarget {
// Check which profile has the strictest policy for failed authentication attempts.
val userToBeWiped = repository.getProfileWithMinFailedUnlockAttemptsForWipe()
- val primaryUser =
- if (Flags.headlessSingleUserFixes()) {
- selectedUserInteractor.getMainUserId() ?: UserHandle.USER_SYSTEM
- } else {
- UserHandle.USER_SYSTEM
- }
+ val primaryUser = selectedUserInteractor.getMainUserId() ?: UserHandle.USER_SYSTEM
return when (userToBeWiped) {
selectedUserInteractor.getSelectedUserId() ->
if (userToBeWiped == primaryUser) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 970fdea..69ab976 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -78,6 +78,8 @@
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.util.concurrency.DelayableExecutor;
+import com.google.android.msdl.domain.MSDLPlayer;
+
import kotlin.Lazy;
import kotlinx.coroutines.CoroutineScope;
@@ -157,6 +159,8 @@
private final @Background DelayableExecutor mBackgroundExecutor;
+ private final MSDLPlayer mMSDLPlayer;
+
// Non-null only if the dialog is in the act of dismissing and has not sent the reason yet.
@Nullable @AuthDialogCallback.DismissedReason private Integer mPendingCallbackReason;
// HAT received from LockSettingsService when credential is verified.
@@ -292,7 +296,8 @@
@NonNull Provider<CredentialViewModel> credentialViewModelProvider,
@NonNull @Background DelayableExecutor bgExecutor,
@NonNull VibratorHelper vibratorHelper,
- Lazy<ViewCapture> lazyViewCapture) {
+ Lazy<ViewCapture> lazyViewCapture,
+ @NonNull MSDLPlayer msdlPlayer) {
super(config.mContext);
mConfig = config;
@@ -309,6 +314,7 @@
.getDimension(R.dimen.biometric_dialog_animation_translation_offset);
mLinearOutSlowIn = Interpolators.LINEAR_OUT_SLOW_IN;
mBiometricCallback = new BiometricCallback();
+ mMSDLPlayer = msdlPlayer;
final BiometricModalities biometricModalities = new BiometricModalities(
Utils.findFirstSensorProperties(fpProps, mConfig.mSensorIds),
@@ -379,7 +385,7 @@
getJankListener(mLayout, TRANSIT,
BiometricViewSizeBinder.ANIMATE_MEDIUM_TO_LARGE_DURATION_MS),
mBackgroundView, mBiometricCallback, mApplicationCoroutineScope,
- vibratorHelper);
+ vibratorHelper, mMSDLPlayer);
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 097ab72..b39aae9 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -89,6 +89,8 @@
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.concurrency.Execution;
+import com.google.android.msdl.domain.MSDLPlayer;
+
import dagger.Lazy;
import kotlin.Unit;
@@ -183,6 +185,7 @@
private final @Background DelayableExecutor mBackgroundExecutor;
private final DisplayInfo mCachedDisplayInfo = new DisplayInfo();
@NonNull private final VibratorHelper mVibratorHelper;
+ @NonNull private final MSDLPlayer mMSDLPlayer;
private final kotlin.Lazy<ViewCapture> mLazyViewCapture;
@@ -742,7 +745,8 @@
@Background DelayableExecutor bgExecutor,
@NonNull UdfpsUtils udfpsUtils,
@NonNull VibratorHelper vibratorHelper,
- Lazy<ViewCapture> daggerLazyViewCapture) {
+ Lazy<ViewCapture> daggerLazyViewCapture,
+ @NonNull MSDLPlayer msdlPlayer) {
mContext = context;
mExecution = execution;
mUserManager = userManager;
@@ -764,6 +768,7 @@
mUdfpsUtils = udfpsUtils;
mApplicationCoroutineScope = applicationCoroutineScope;
mVibratorHelper = vibratorHelper;
+ mMSDLPlayer = msdlPlayer;
mLogContextInteractor = logContextInteractor;
mPromptSelectorInteractor = promptSelectorInteractorProvider;
@@ -1327,7 +1332,7 @@
wakefulnessLifecycle, userManager, lockPatternUtils,
mInteractionJankMonitor, mPromptSelectorInteractor, viewModel,
mCredentialViewModelProvider, bgExecutor, mVibratorHelper,
- mLazyViewCapture);
+ mLazyViewCapture, mMSDLPlayer);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
index 0b440ad..e7e8d8f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
@@ -25,7 +25,6 @@
import android.hardware.biometrics.Flags
import android.hardware.face.FaceManager
import android.util.Log
-import android.view.HapticFeedbackConstants
import android.view.MotionEvent
import android.view.View
import android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO
@@ -59,6 +58,7 @@
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.res.R
import com.android.systemui.statusbar.VibratorHelper
+import com.google.android.msdl.domain.MSDLPlayer
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.combine
@@ -83,6 +83,7 @@
legacyCallback: Spaghetti.Callback,
applicationScope: CoroutineScope,
vibratorHelper: VibratorHelper,
+ msdlPlayer: MSDLPlayer,
): Spaghetti {
val accessibilityManager = view.context.getSystemService(AccessibilityManager::class.java)!!
@@ -434,21 +435,27 @@
// Play haptics
launch {
viewModel.hapticsToPlay.collect { haptics ->
- if (haptics.hapticFeedbackConstant != HapticFeedbackConstants.NO_HAPTICS) {
- if (haptics.flag != null) {
- vibratorHelper.performHapticFeedback(
- view,
- haptics.hapticFeedbackConstant,
- haptics.flag,
- )
- } else {
- vibratorHelper.performHapticFeedback(
- view,
- haptics.hapticFeedbackConstant,
- )
+ when (haptics) {
+ is PromptViewModel.HapticsToPlay.HapticConstant -> {
+ if (haptics.flag != null) {
+ vibratorHelper.performHapticFeedback(
+ view,
+ haptics.constant,
+ haptics.flag,
+ )
+ } else {
+ vibratorHelper.performHapticFeedback(
+ view,
+ haptics.constant,
+ )
+ }
}
- viewModel.clearHaptics()
+ is PromptViewModel.HapticsToPlay.MSDL -> {
+ msdlPlayer.playToken(haptics.token, haptics.properties)
+ }
+ is PromptViewModel.HapticsToPlay.None -> {}
}
+ viewModel.clearHaptics()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
index 85c3ae3..d69e875 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
@@ -18,13 +18,11 @@
import android.animation.Animator
import android.animation.AnimatorSet
-import android.animation.ValueAnimator
import android.graphics.Outline
import android.graphics.Rect
import android.transition.AutoTransition
import android.transition.TransitionManager
import android.util.TypedValue
-import android.view.Surface
import android.view.View
import android.view.ViewGroup
import android.view.ViewOutlineProvider
@@ -413,13 +411,12 @@
ANIMATE_SMALL_TO_MEDIUM_DURATION_MS.toLong()
)
- TransitionManager.beginDelayedTransition(view, autoTransition)
-
if (position.isLeft) {
flipConstraintSet.applyTo(view)
} else {
mediumConstraintSet.applyTo(view)
}
+ TransitionManager.beginDelayedTransition(view, autoTransition)
}
size.isMedium -> {
if (position.isLeft) {
@@ -428,14 +425,18 @@
mediumConstraintSet.applyTo(view)
}
}
- size.isLarge && currentSize.isMedium -> {
+ size.isLarge -> {
val autoTransition = AutoTransition()
autoTransition.setDuration(
- ANIMATE_MEDIUM_TO_LARGE_DURATION_MS.toLong()
+ if (currentSize.isSmall) {
+ ANIMATE_SMALL_TO_MEDIUM_DURATION_MS.toLong()
+ } else {
+ ANIMATE_MEDIUM_TO_LARGE_DURATION_MS.toLong()
+ }
)
- TransitionManager.beginDelayedTransition(view, autoTransition)
largeConstraintSet.applyTo(view)
+ TransitionManager.beginDelayedTransition(view, autoTransition)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
index 4c2fe07..168ba11 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
@@ -35,7 +35,9 @@
import android.util.RotationUtils
import android.view.HapticFeedbackConstants
import android.view.MotionEvent
+import com.android.keyguard.AuthInteractionProperties
import com.android.launcher3.icons.IconProvider
+import com.android.systemui.Flags.msdlFeedback
import com.android.systemui.biometrics.UdfpsUtils
import com.android.systemui.biometrics.Utils
import com.android.systemui.biometrics.Utils.isSystem
@@ -53,6 +55,8 @@
import com.android.systemui.keyguard.shared.model.AcquiredFingerprintAuthenticationStatus
import com.android.systemui.res.R
import com.android.systemui.util.kotlin.combine
+import com.google.android.msdl.data.model.MSDLToken
+import com.google.android.msdl.domain.InteractionProperties
import javax.inject.Inject
import kotlinx.coroutines.Job
import kotlinx.coroutines.coroutineScope
@@ -245,8 +249,9 @@
private val _forceLargeSize = MutableStateFlow(false)
private val _forceMediumSize = MutableStateFlow(false)
- private val _hapticsToPlay =
- MutableStateFlow(HapticsToPlay(HapticFeedbackConstants.NO_HAPTICS, /* flag= */ null))
+ private val authInteractionProperties = AuthInteractionProperties()
+ private val _hapticsToPlay: MutableStateFlow<HapticsToPlay> =
+ MutableStateFlow(HapticsToPlay.None)
/** Event fired to the view indicating a [HapticsToPlay] */
val hapticsToPlay = _hapticsToPlay.asStateFlow()
@@ -939,26 +944,52 @@
}
private fun vibrateOnSuccess() {
- _hapticsToPlay.value =
- HapticsToPlay(
- HapticFeedbackConstants.BIOMETRIC_CONFIRM,
- null,
- )
+ val haptics =
+ if (msdlFeedback()) {
+ HapticsToPlay.MSDL(MSDLToken.UNLOCK, authInteractionProperties)
+ } else {
+ HapticsToPlay.HapticConstant(
+ HapticFeedbackConstants.BIOMETRIC_CONFIRM,
+ flag = null,
+ )
+ }
+ _hapticsToPlay.value = haptics
}
private fun vibrateOnError() {
- _hapticsToPlay.value =
- HapticsToPlay(
- HapticFeedbackConstants.BIOMETRIC_REJECT,
- null,
- )
+ val haptics =
+ if (msdlFeedback()) {
+ HapticsToPlay.MSDL(MSDLToken.FAILURE, authInteractionProperties)
+ } else {
+ HapticsToPlay.HapticConstant(
+ HapticFeedbackConstants.BIOMETRIC_REJECT,
+ flag = null,
+ )
+ }
+ _hapticsToPlay.value = haptics
}
/** Clears the [hapticsToPlay] variable by setting its constant to the NO_HAPTICS default. */
fun clearHaptics() {
- _hapticsToPlay.update { previous ->
- HapticsToPlay(HapticFeedbackConstants.NO_HAPTICS, previous.flag)
- }
+ _hapticsToPlay.update { HapticsToPlay.None }
+ }
+
+ /** The state of haptic feedback to play. */
+ sealed interface HapticsToPlay {
+ /**
+ * Haptics using [HapticFeedbackConstants]. It is composed by a [HapticFeedbackConstants]
+ * and a [HapticFeedbackConstants] flag.
+ */
+ data class HapticConstant(val constant: Int, val flag: Int?) : HapticsToPlay
+
+ /**
+ * Haptics using MSDL feedback. It is composed by a [MSDLToken] and optional
+ * [InteractionProperties]
+ */
+ data class MSDL(val token: MSDLToken, val properties: InteractionProperties?) :
+ HapticsToPlay
+
+ data object None : HapticsToPlay
}
companion object {
@@ -1095,9 +1126,3 @@
val isStarted: Boolean
get() = this == Normal || this == Delayed
}
-
-/**
- * The state of haptic feedback to play. It is composed by a [HapticFeedbackConstants] and a
- * [HapticFeedbackConstants] flag.
- */
-data class HapticsToPlay(val hapticFeedbackConstant: Int, val flag: Int?)
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractor.kt
index f36ef66..8b5a09b 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractor.kt
@@ -34,10 +34,14 @@
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.doze.DozeLogger
+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.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import com.android.systemui.util.EmergencyDialerConstants
+import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
@@ -69,6 +73,7 @@
private val emergencyDialerIntentFactory: EmergencyDialerIntentFactory,
private val metricsLogger: MetricsLogger,
private val dozeLogger: DozeLogger,
+ private val sceneInteractor: Lazy<SceneInteractor>,
) {
/** The bouncer action button. If `null`, the button should not be shown. */
val actionButton: Flow<BouncerActionButtonModel?> =
@@ -158,14 +163,17 @@
}
private fun prepareToPerformAction() {
- // TODO(b/308001302): Trigger occlusion and resetting bouncer state.
+ if (SceneContainerFlag.isEnabled) {
+ sceneInteractor.get().changeScene(Scenes.Lockscreen, "Bouncer action button clicked")
+ }
+
metricsLogger.action(MetricsEvent.ACTION_EMERGENCY_CALL)
activityTaskManager.stopSystemLockTaskMode()
}
@SuppressLint("MissingPermission")
private fun returnToCall() {
- telecomManager?.showInCallScreen(/* showDialpad = */ false)
+ telecomManager?.showInCallScreen(/* showDialpad= */ false)
}
private val <T> Flow<T>.asUnitFlow: Flow<Unit>
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt
index cc8dce79..49dadce 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt
@@ -2,13 +2,11 @@
import android.view.ViewGroup
import com.android.keyguard.KeyguardMessageAreaController
-import com.android.keyguard.ViewMediatorCallback
import com.android.keyguard.dagger.KeyguardBouncerComponent
-import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags
import com.android.systemui.bouncer.ui.BouncerDialogFactory
+import com.android.systemui.bouncer.ui.viewmodel.BouncerContainerViewModel
import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel
import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel
import com.android.systemui.dagger.SysUISingleton
@@ -39,12 +37,9 @@
data class ComposeBouncerDependencies
@Inject
constructor(
- val legacyInteractor: PrimaryBouncerInteractor,
val viewModelFactory: BouncerSceneContentViewModel.Factory,
val dialogFactory: BouncerDialogFactory,
- val authenticationInteractor: AuthenticationInteractor,
- val viewMediatorCallback: ViewMediatorCallback?,
- val selectedUserInteractor: SelectedUserInteractor,
+ val bouncerContainerViewModelFactory: BouncerContainerViewModel.Factory,
)
/**
@@ -63,12 +58,9 @@
val deps = composeBouncerDependencies.get()
ComposeBouncerViewBinder.bind(
view,
- deps.legacyInteractor,
deps.viewModelFactory,
deps.dialogFactory,
- deps.authenticationInteractor,
- deps.selectedUserInteractor,
- deps.viewMediatorCallback,
+ deps.bouncerContainerViewModelFactory,
)
} else {
val deps = legacyBouncerDependencies.get()
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt
index c4bbd9c..b5e54d5 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt
@@ -5,89 +5,55 @@
import androidx.activity.OnBackPressedDispatcherOwner
import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
import androidx.compose.ui.platform.ComposeView
-import androidx.core.view.isVisible
+import androidx.core.view.isGone
import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.repeatOnLifecycle
-import com.android.keyguard.ViewMediatorCallback
-import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.bouncer.ui.BouncerDialogFactory
import com.android.systemui.bouncer.ui.composable.BouncerContainer
+import com.android.systemui.bouncer.ui.viewmodel.BouncerContainerViewModel
import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel
+import com.android.systemui.lifecycle.WindowLifecycleState
import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.user.domain.interactor.SelectedUserInteractor
-import kotlinx.coroutines.flow.collectLatest
-import kotlinx.coroutines.launch
+import com.android.systemui.lifecycle.setSnapshotBinding
+import com.android.systemui.lifecycle.viewModel
+import kotlinx.coroutines.awaitCancellation
/** View binder responsible for binding the compose version of the bouncer. */
object ComposeBouncerViewBinder {
fun bind(
view: ViewGroup,
- legacyInteractor: PrimaryBouncerInteractor,
viewModelFactory: BouncerSceneContentViewModel.Factory,
dialogFactory: BouncerDialogFactory,
- authenticationInteractor: AuthenticationInteractor,
- selectedUserInteractor: SelectedUserInteractor,
- viewMediatorCallback: ViewMediatorCallback?,
+ bouncerContainerViewModelFactory: BouncerContainerViewModel.Factory,
) {
- view.addView(
- ComposeView(view.context).apply {
- repeatWhenAttached {
- repeatOnLifecycle(Lifecycle.State.CREATED) {
- setViewTreeOnBackPressedDispatcherOwner(
- object : OnBackPressedDispatcherOwner {
- override val onBackPressedDispatcher =
- OnBackPressedDispatcher().apply {
- setOnBackInvokedDispatcher(
- view.viewRootImpl.onBackInvokedDispatcher
- )
- }
-
- override val lifecycle: Lifecycle =
- this@repeatWhenAttached.lifecycle
- }
- )
- setContent { BouncerContainer(viewModelFactory, dialogFactory) }
- }
- }
- }
- )
-
view.repeatWhenAttached {
- repeatOnLifecycle(Lifecycle.State.CREATED) {
- launch {
- legacyInteractor.isShowing.collectLatest { bouncerShowing ->
- view.isVisible = bouncerShowing
- }
- }
-
- launch {
- authenticationInteractor.onAuthenticationResult.collectLatest {
- authenticationSucceeded ->
- if (authenticationSucceeded) {
- // Some dismiss actions require that keyguard be dismissed right away or
- // deferred until something else later on dismisses keyguard (eg. end of
- // a hide animation).
- val deferKeyguardDone =
- legacyInteractor.bouncerDismissAction?.onDismissAction?.onDismiss()
- legacyInteractor.setDismissAction(null, null)
-
- viewMediatorCallback?.let {
- val selectedUserId = selectedUserInteractor.getSelectedUserId()
- if (deferKeyguardDone == true) {
- it.keyguardDonePending(selectedUserId)
- } else {
- it.keyguardDone(selectedUserId)
+ view.viewModel(
+ minWindowLifecycleState = WindowLifecycleState.ATTACHED,
+ factory = { bouncerContainerViewModelFactory.create() },
+ traceName = "ComposeBouncerViewBinder",
+ ) { viewModel ->
+ try {
+ view.setViewTreeOnBackPressedDispatcherOwner(
+ object : OnBackPressedDispatcherOwner {
+ override val onBackPressedDispatcher =
+ OnBackPressedDispatcher().apply {
+ setOnBackInvokedDispatcher(
+ view.viewRootImpl.onBackInvokedDispatcher
+ )
}
- }
+
+ override val lifecycle: Lifecycle = this@repeatWhenAttached.lifecycle
}
- }
- }
- launch {
- legacyInteractor.startingDisappearAnimation.collectLatest {
- it.run()
- legacyInteractor.hide()
- }
+ )
+
+ view.addView(
+ ComposeView(view.context).apply {
+ setContent { BouncerContainer(viewModelFactory, dialogFactory) }
+ }
+ )
+ view.setSnapshotBinding { view.isGone = !viewModel.isVisible }
+ awaitCancellation()
+ } finally {
+ view.removeAllViews()
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerHapticHelper.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerHapticHelper.kt
new file mode 100644
index 0000000..1faacff
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/helper/BouncerHapticHelper.kt
@@ -0,0 +1,73 @@
+/*
+ * 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.bouncer.ui.helper
+
+import android.view.HapticFeedbackConstants
+import android.view.View
+import com.android.keyguard.AuthInteractionProperties
+import com.android.systemui.Flags
+//noinspection CleanArchitectureDependencyViolation: Data layer only referenced for this enum class
+import com.google.android.msdl.data.model.MSDLToken
+import com.google.android.msdl.domain.MSDLPlayer
+
+/** A helper object to deliver haptic feedback in bouncer interactions. */
+object BouncerHapticHelper {
+
+ private val authInteractionProperties = AuthInteractionProperties()
+
+ /**
+ * Deliver MSDL feedback as a result of authenticating through a bouncer.
+ *
+ * @param[authenticationSucceeded] Whether the authentication was successful or not.
+ * @param[player] The [MSDLPlayer] that delivers the correct feedback.
+ */
+ fun playMSDLAuthenticationFeedback(
+ authenticationSucceeded: Boolean,
+ player: MSDLPlayer?,
+ ) {
+ if (player == null || !Flags.msdlFeedback()) {
+ return
+ }
+
+ val token =
+ if (authenticationSucceeded) {
+ MSDLToken.UNLOCK
+ } else {
+ MSDLToken.FAILURE
+ }
+ player.playToken(token, authInteractionProperties)
+ }
+
+ /**
+ * Deliver feedback when dragging through cells in the pattern bouncer. This function can play
+ * MSDL feedback using a [MSDLPlayer], or fallback to a default haptic feedback using the
+ * [View.performHapticFeedback] API and a [View].
+ *
+ * @param[player] [MSDLPlayer] for MSDL feedback.
+ * @param[view] A [View] for default haptic feedback using [View.performHapticFeedback]
+ */
+ fun playPatternDotFeedback(player: MSDLPlayer?, view: View?) {
+ if (player == null || !Flags.msdlFeedback()) {
+ view?.performHapticFeedback(
+ HapticFeedbackConstants.VIRTUAL_KEY,
+ HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING,
+ )
+ } else {
+ player.playToken(MSDLToken.DRAG_INDICATOR)
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerContainerViewModel.kt
new file mode 100644
index 0000000..d223657
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerContainerViewModel.kt
@@ -0,0 +1,84 @@
+/*
+ * 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.bouncer.ui.viewmodel
+
+import androidx.compose.runtime.getValue
+import com.android.keyguard.ViewMediatorCallback
+import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.lifecycle.ExclusiveActivatable
+import com.android.systemui.lifecycle.Hydrator
+import com.android.systemui.user.domain.interactor.SelectedUserInteractor
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.launch
+
+class BouncerContainerViewModel
+@AssistedInject
+constructor(
+ private val legacyInteractor: PrimaryBouncerInteractor,
+ private val authenticationInteractor: AuthenticationInteractor,
+ private val selectedUserInteractor: SelectedUserInteractor,
+ private val viewMediatorCallback: ViewMediatorCallback?,
+) : ExclusiveActivatable() {
+
+ private val hydrator = Hydrator("BouncerContainerViewModel")
+
+ val isVisible: Boolean by
+ hydrator.hydratedStateOf(traceName = "isVisible", source = legacyInteractor.isShowing)
+
+ override suspend fun onActivated(): Nothing {
+ coroutineScope {
+ launch {
+ authenticationInteractor.onAuthenticationResult.collect { authenticationSucceeded ->
+ if (authenticationSucceeded) {
+ // Some dismiss actions require that keyguard be dismissed right away or
+ // deferred until something else later on dismisses keyguard (eg. end of
+ // a hide animation).
+ val deferKeyguardDone =
+ legacyInteractor.bouncerDismissAction?.onDismissAction?.onDismiss()
+ legacyInteractor.setDismissAction(null, null)
+
+ viewMediatorCallback?.let {
+ val selectedUserId = selectedUserInteractor.getSelectedUserId()
+ if (deferKeyguardDone == true) {
+ it.keyguardDonePending(selectedUserId)
+ } else {
+ it.keyguardDone(selectedUserId)
+ }
+ }
+ }
+ }
+ }
+
+ launch {
+ legacyInteractor.startingDisappearAnimation.collect {
+ it.run()
+ legacyInteractor.hide()
+ }
+ }
+
+ hydrator.activate()
+ }
+ }
+
+ @AssistedFactory
+ interface Factory {
+ fun create(): BouncerContainerViewModel
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerUserActionsViewModel.kt
similarity index 90%
rename from packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModel.kt
rename to packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerUserActionsViewModel.kt
index 2d57e5b..4fe6fc6 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerUserActionsViewModel.kt
@@ -22,7 +22,7 @@
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.map
@@ -31,11 +31,11 @@
* Models UI state for user actions that can lead to navigation to other scenes when showing the
* bouncer scene.
*/
-class BouncerSceneActionsViewModel
+class BouncerUserActionsViewModel
@AssistedInject
constructor(
private val bouncerInteractor: BouncerInteractor,
-) : SceneActionsViewModel() {
+) : UserActionsViewModel() {
override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
bouncerInteractor.dismissDestination
@@ -50,6 +50,6 @@
@AssistedFactory
interface Factory {
- fun create(): BouncerSceneActionsViewModel
+ fun create(): BouncerUserActionsViewModel
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
index d2caefd..83d4091 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
@@ -34,8 +34,6 @@
import com.android.systemui.classifier.FalsingDataProvider.SessionListener;
import com.android.systemui.classifier.HistoryTracker.BeliefListener;
import com.android.systemui.dagger.qualifiers.TestHarness;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -76,7 +74,6 @@
private final boolean mTestHarness;
private final MetricsLogger mMetricsLogger;
private int mIsFalseTouchCalls;
- private FeatureFlags mFeatureFlags;
private static final Queue<String> RECENT_INFO_LOG =
new ArrayDeque<>(RECENT_INFO_LOG_SIZE + 1);
private static final Queue<DebugSwipeRecord> RECENT_SWIPES =
@@ -186,8 +183,7 @@
DoubleTapClassifier doubleTapClassifier, HistoryTracker historyTracker,
KeyguardStateController keyguardStateController,
AccessibilityManager accessibilityManager,
- @TestHarness boolean testHarness,
- FeatureFlags featureFlags) {
+ @TestHarness boolean testHarness) {
mDataProvider = falsingDataProvider;
mMetricsLogger = metricsLogger;
mClassifiers = classifiers;
@@ -198,7 +194,6 @@
mKeyguardStateController = keyguardStateController;
mAccessibilityManager = accessibilityManager;
mTestHarness = testHarness;
- mFeatureFlags = featureFlags;
mDataProvider.addSessionListener(mSessionListener);
mDataProvider.addGestureCompleteListener(mGestureFinalizedListener);
@@ -399,8 +394,8 @@
|| mDataProvider.isA11yAction()
|| mDataProvider.isFromTrackpad()
|| mDataProvider.isFromKeyboard()
- || (mFeatureFlags.isEnabled(Flags.FALSING_OFF_FOR_UNFOLDED)
- && mDataProvider.isUnfolded());
+ || !mDataProvider.isTouchScreenSource()
+ || mDataProvider.isUnfolded();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
index 2eca02c..962ab99 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
@@ -21,6 +21,7 @@
import android.hardware.SensorManager;
import android.hardware.biometrics.BiometricSourceType;
import android.util.Log;
+import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -28,6 +29,7 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.Flags;
import com.android.systemui.communal.domain.interactor.CommunalInteractor;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
@@ -343,7 +345,9 @@
// will be ignored by the collector until another MotionEvent.ACTION_DOWN is passed in.
// avoidGesture must be called immediately following the MotionEvent.ACTION_DOWN, before
// any other events are processed, otherwise the whole gesture will be recorded.
- if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ //
+ // We should only delay processing of these events for touchscreen sources
+ if (ev.getActionMasked() == MotionEvent.ACTION_DOWN && isTouchscreenSource(ev)) {
// Make a copy of ev, since it will be recycled after we exit this method.
mPendingDownEvent = MotionEvent.obtain(ev);
mAvoidGesture = false;
@@ -410,6 +414,22 @@
mFalsingDataProvider.onA11yAction();
}
+ /**
+ * returns {@code true} if the device supports Touchscreen, {@code false} otherwise. Defaults to
+ * {@code true} if the device is {@code null}
+ */
+ private boolean isTouchscreenSource(MotionEvent ev) {
+ if (!Flags.nonTouchscreenDevicesBypassFalsing()) {
+ return true;
+ }
+ InputDevice device = ev.getDevice();
+ if (device != null) {
+ return device.supportsSource(InputDevice.SOURCE_TOUCHSCREEN);
+ } else {
+ return true;
+ }
+ }
+
private boolean shouldSessionBeActive() {
return mScreenOn
&& (mState == StatusBarState.KEYGUARD)
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
index 1501701..769976e 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
@@ -20,11 +20,13 @@
import android.hardware.devicestate.DeviceStateManager.FoldStateListener;
import android.util.DisplayMetrics;
+import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.MotionEvent.PointerCoords;
import android.view.MotionEvent.PointerProperties;
+import com.android.systemui.Flags;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dock.DockManager;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -281,6 +283,9 @@
}
public boolean isFromTrackpad() {
+ if (Flags.nonTouchscreenDevicesBypassFalsing()) {
+ return false;
+ }
if (mRecentMotionEvents.isEmpty()) {
return false;
}
@@ -290,6 +295,25 @@
|| classification == MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE;
}
+ /**
+ * returns {@code true} if the device supports Touchscreen, {@code false} otherwise. Defaults to
+ * {@code true} if the device is {@code null}
+ */
+ public boolean isTouchScreenSource() {
+ if (!Flags.nonTouchscreenDevicesBypassFalsing()) {
+ return true;
+ }
+ if (mRecentMotionEvents.isEmpty()) {
+ return true;
+ }
+ InputDevice device = mRecentMotionEvents.get(mRecentMotionEvents.size() - 1).getDevice();
+ if (device != null) {
+ return device.supportsSource(InputDevice.SOURCE_TOUCHSCREEN);
+ } else {
+ return true;
+ }
+ }
+
private void recalculateData() {
if (!mDirty) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayWindow.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayWindow.java
index 0dc6fda..dc3b50c 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayWindow.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayWindow.java
@@ -27,6 +27,7 @@
import android.view.WindowInsets;
import android.view.WindowManager;
+import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
import com.android.internal.policy.PhoneWindow;
import com.android.systemui.clipboardoverlay.dagger.ClipboardOverlayModule.OverlayWindowContext;
import com.android.systemui.screenshot.FloatingWindowUtil;
@@ -44,6 +45,7 @@
private final Context mContext;
private final WindowManager mWindowManager;
+ private final ViewCaptureAwareWindowManager mViewCaptureAwareWindowManager;
private final WindowManager.LayoutParams mWindowLayoutParams;
private boolean mKeyboardVisible;
@@ -52,7 +54,9 @@
private Runnable mOnOrientationChangeListener;
@Inject
- ClipboardOverlayWindow(@OverlayWindowContext Context context) {
+ ClipboardOverlayWindow(@OverlayWindowContext Context context,
+ @OverlayWindowContext ViewCaptureAwareWindowManager viewCaptureAwareWindowManager,
+ @OverlayWindowContext WindowManager windowManager) {
super(context);
mContext = context;
mOrientation = mContext.getResources().getConfiguration().orientation;
@@ -61,10 +65,11 @@
requestFeature(Window.FEATURE_NO_TITLE);
requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
setBackgroundDrawableResource(android.R.color.transparent);
- mWindowManager = mContext.getSystemService(WindowManager.class);
+ mWindowManager = windowManager;
+ mViewCaptureAwareWindowManager = viewCaptureAwareWindowManager;
mWindowLayoutParams = FloatingWindowUtil.getFloatingWindowParams();
mWindowLayoutParams.setTitle("ClipboardOverlay");
- setWindowManager(mWindowManager, null, null);
+ setWindowManager(windowManager, null, null);
setWindowFocusable(false);
}
@@ -81,10 +86,12 @@
attach();
withWindowAttached(() -> {
- WindowInsets currentInsets = mWindowManager.getCurrentWindowMetrics().getWindowInsets();
+ WindowInsets currentInsets = mWindowManager.getCurrentWindowMetrics()
+ .getWindowInsets();
mKeyboardVisible = currentInsets.isVisible(WindowInsets.Type.ime());
peekDecorView().getViewTreeObserver().addOnGlobalLayoutListener(() -> {
- WindowInsets insets = mWindowManager.getCurrentWindowMetrics().getWindowInsets();
+ WindowInsets insets = mWindowManager.getCurrentWindowMetrics()
+ .getWindowInsets();
boolean keyboardVisible = insets.isVisible(WindowInsets.Type.ime());
if (keyboardVisible != mKeyboardVisible) {
mKeyboardVisible = keyboardVisible;
@@ -105,7 +112,7 @@
void remove() {
final View decorView = peekDecorView();
if (decorView != null && decorView.isAttachedToWindow()) {
- mWindowManager.removeViewImmediate(decorView);
+ mViewCaptureAwareWindowManager.removeViewImmediate(decorView);
}
}
@@ -139,7 +146,7 @@
if (decorView.isAttachedToWindow()) {
return;
}
- mWindowManager.addView(decorView, mWindowLayoutParams);
+ mViewCaptureAwareWindowManager.addView(decorView, mWindowLayoutParams);
decorView.requestApplyInsets();
}
@@ -160,7 +167,7 @@
}
final View decorView = peekDecorView();
if (decorView != null && decorView.isAttachedToWindow()) {
- mWindowManager.updateViewLayout(decorView, mWindowLayoutParams);
+ mViewCaptureAwareWindowManager.updateViewLayout(decorView, mWindowLayoutParams);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java
index ff9fba4..307a07f 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java
@@ -18,17 +18,24 @@
import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
+import static com.android.systemui.Flags.enableViewCaptureTracing;
+import static com.android.systemui.util.ConvenienceExtensionsKt.toKotlinLazy;
+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import android.content.Context;
import android.hardware.display.DisplayManager;
import android.view.Display;
import android.view.LayoutInflater;
+import android.view.WindowManager;
+import com.android.app.viewcapture.ViewCapture;
+import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
import com.android.systemui.clipboardoverlay.ClipboardOverlayView;
import com.android.systemui.res.R;
import com.android.systemui.settings.DisplayTracker;
+import dagger.Lazy;
import dagger.Module;
import dagger.Provides;
@@ -61,6 +68,28 @@
R.layout.clipboard_overlay, null);
}
+ /**
+ *
+ */
+ @Provides
+ @OverlayWindowContext
+ static WindowManager provideWindowManager(@OverlayWindowContext Context context) {
+ return context.getSystemService(WindowManager.class);
+ }
+
+ /**
+ *
+ */
+ @Provides
+ @OverlayWindowContext
+ static ViewCaptureAwareWindowManager provideViewCaptureAwareWindowManager(
+ @OverlayWindowContext WindowManager windowManager,
+ Lazy<ViewCapture> daggerLazyViewCapture) {
+ return new ViewCaptureAwareWindowManager(windowManager,
+ /* lazyViewCapture= */ toKotlinLazy(daggerLazyViewCapture),
+ /* isViewCaptureEnabled= */ enableViewCaptureTracing());
+ }
+
@Qualifier
@Documented
@Retention(RUNTIME)
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt
index b6ace81..9c4736a 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt
@@ -27,6 +27,7 @@
import android.view.accessibility.AccessibilityNodeInfo
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
+import com.android.systemui.log.LongPressHandlingViewLogger
import com.android.systemui.shade.TouchLogger
import kotlin.math.pow
import kotlin.math.sqrt
@@ -42,6 +43,8 @@
context: Context,
attrs: AttributeSet?,
longPressDuration: () -> Long,
+ allowedTouchSlop: Int = ViewConfiguration.getTouchSlop(),
+ logger: LongPressHandlingViewLogger? = null,
) :
View(
context,
@@ -97,6 +100,8 @@
},
onSingleTapDetected = { listener?.onSingleTapDetected(this@LongPressHandlingView) },
longPressDuration = longPressDuration,
+ allowedTouchSlop = allowedTouchSlop,
+ logger = logger,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandler.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandler.kt
index d3fc610..4e38a49 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandler.kt
@@ -17,7 +17,7 @@
package com.android.systemui.common.ui.view
-import android.view.ViewConfiguration
+import com.android.systemui.log.LongPressHandlingViewLogger
import kotlinx.coroutines.DisposableHandle
/** Encapsulates logic to handle complex touch interactions with a [LongPressHandlingView]. */
@@ -35,6 +35,14 @@
private val onSingleTapDetected: () -> Unit,
/** Time for the touch to be considered a long-press in ms */
var longPressDuration: () -> Long,
+ /**
+ * Default touch slop that is allowed, if the movement between [MotionEventModel.Down] and
+ * [MotionEventModel.Up] is more than [allowedTouchSlop] then the touch is not processed as
+ * single tap or a long press.
+ */
+ val allowedTouchSlop: Int,
+ /** Optional logger that can be passed in to log touch events */
+ val logger: LongPressHandlingViewLogger? = null,
) {
sealed class MotionEventModel {
object Other : MotionEventModel()
@@ -70,22 +78,26 @@
true
}
is MotionEventModel.Move -> {
- if (event.distanceMoved > ViewConfiguration.getTouchSlop()) {
+ if (event.distanceMoved > allowedTouchSlop) {
+ logger?.cancelingLongPressDueToTouchSlop(event.distanceMoved, allowedTouchSlop)
cancelScheduledLongPress()
}
false
}
is MotionEventModel.Up -> {
+ logger?.onUpEvent(event.distanceMoved, allowedTouchSlop, event.gestureDuration)
cancelScheduledLongPress()
if (
- event.distanceMoved <= ViewConfiguration.getTouchSlop() &&
+ event.distanceMoved <= allowedTouchSlop &&
event.gestureDuration < longPressDuration()
) {
+ logger?.dispatchingSingleTap()
dispatchSingleTap()
}
false
}
is MotionEventModel.Cancel -> {
+ logger?.motionEventCancelled()
cancelScheduledLongPress()
false
}
@@ -97,15 +109,18 @@
x: Int,
y: Int,
) {
+ val duration = longPressDuration()
+ logger?.schedulingLongPress(duration)
scheduledLongPressHandle =
postDelayed(
{
+ logger?.longPressTriggered()
dispatchLongPress(
x = x,
y = y,
)
},
- longPressDuration(),
+ duration,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
index 21a704d..8818c3a 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
@@ -202,6 +202,13 @@
return context.getSystemService(CaptioningManager.class);
}
+ @Provides
+ @Singleton
+ static UserScopedService<CaptioningManager> provideUserScopedCaptioningManager(
+ Context context) {
+ return new UserScopedServiceImpl<>(context, CaptioningManager.class);
+ }
+
/** */
@Provides
@Singleton
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index 1c263ae..113e001 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -475,7 +475,7 @@
mLifecycleOwner,
new HashSet<>(Arrays.asList(
dreamComplicationComponent.getHideComplicationTouchHandler(),
- dreamOverlayComponent.getCommunalTouchHandler())));
+ dreamOverlayComponent.getCommunalTouchHandler())), TAG);
setLifecycleStateLocked(Lifecycle.State.STARTED);
@@ -552,7 +552,8 @@
}
private void updateGestureBlockingLocked() {
- final boolean shouldBlock = !isDreamInPreviewMode() && !mShadeExpanded && !mBouncerShowing;
+ final boolean shouldBlock = mStarted && !mShadeExpanded && !mBouncerShowing
+ && !isDreamInPreviewMode();
if (shouldBlock) {
mGestureInteractor.addGestureBlockedMatcher(DREAM_TYPE_MATCHER,
diff --git a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
index 87eeebf..43855d9 100644
--- a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
@@ -19,13 +19,12 @@
import android.hardware.input.InputManager
import android.hardware.input.InputManager.KeyGestureEventListener
import android.hardware.input.KeyGestureEvent
+import android.os.SystemProperties
import com.android.systemui.CoreStartable
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.contextualeducation.GestureType
import com.android.systemui.contextualeducation.GestureType.ALL_APPS
import com.android.systemui.contextualeducation.GestureType.BACK
-import com.android.systemui.contextualeducation.GestureType.HOME
-import com.android.systemui.contextualeducation.GestureType.OVERVIEW
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.education.dagger.ContextualEducationModule.EduClock
@@ -37,7 +36,10 @@
import java.time.Clock
import java.util.concurrent.Executor
import javax.inject.Inject
-import kotlin.time.Duration.Companion.hours
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.days
+import kotlin.time.DurationUnit
+import kotlin.time.toDuration
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
@@ -60,7 +62,21 @@
companion object {
const val TAG = "KeyboardTouchpadEduInteractor"
const val MAX_SIGNAL_COUNT: Int = 2
- val usageSessionDuration = 72.hours
+ const val MAX_EDUCATION_SHOW_COUNT: Int = 2
+ val usageSessionDuration =
+ getDurationForConfig("persist.contextual_edu.usage_session_sec", 3.days)
+ val minIntervalBetweenEdu =
+ getDurationForConfig("persist.contextual_edu.edu_interval_sec", 7.days)
+
+ private fun getDurationForConfig(
+ systemPropertyKey: String,
+ defaultDuration: Duration
+ ): Duration =
+ SystemProperties.getLong(
+ systemPropertyKey,
+ /* defaultValue= */ defaultDuration.inWholeSeconds
+ )
+ .toDuration(DurationUnit.SECONDS)
}
private val _educationTriggered = MutableStateFlow<EducationInfo?>(null)
@@ -68,11 +84,9 @@
private val keyboardShortcutTriggered: Flow<GestureType> = conflatedCallbackFlow {
val listener = KeyGestureEventListener { event ->
+ // Only store keyboard shortcut time for gestures providing keyboard education
val shortcutType =
when (event.keyGestureType) {
- KeyGestureEvent.KEY_GESTURE_TYPE_BACK -> BACK
- KeyGestureEvent.KEY_GESTURE_TYPE_HOME -> HOME
- KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS -> OVERVIEW
KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS -> ALL_APPS
else -> null
}
@@ -132,10 +146,20 @@
}
private fun isEducationNeeded(model: GestureEduModel): Boolean {
- // Todo: b/354884305 - add complete education logic to show education in correct scenarios
+ val lessThanMaxEduCount = model.educationShownCount < MAX_EDUCATION_SHOW_COUNT
val noShortcutTriggered = model.lastShortcutTriggeredTime == null
val signalCountReached = model.signalCount >= MAX_SIGNAL_COUNT
- return noShortcutTriggered && signalCountReached
+ val isPreviousEduOlderThanMinInterval =
+ if (model.educationShownCount == 1) {
+ model.lastEducationTime
+ ?.plusSeconds(minIntervalBetweenEdu.inWholeSeconds)
+ ?.isBefore(clock.instant()) ?: true
+ } else true
+
+ return lessThanMaxEduCount &&
+ noShortcutTriggered &&
+ signalCountReached &&
+ isPreviousEduOlderThanMinInterval
}
private fun isUsageSessionExpired(model: GestureEduModel): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index bb73f56..95cd9eb 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -98,9 +98,6 @@
@JvmField
val AUTO_PIN_CONFIRMATION = releasedFlag("auto_pin_confirmation", "auto_pin_confirmation")
- // TODO(b/262859270): Tracking Bug
- @JvmField val FALSING_OFF_FOR_UNFOLDED = releasedFlag("falsing_off_for_unfolded")
-
/** Enables code to show contextual loyalty cards in wallet entrypoints */
// TODO(b/294110497): Tracking Bug
@JvmField
@@ -203,12 +200,6 @@
@JvmField
val INCOMPATIBLE_CHARGING_BATTERY_ICON = releasedFlag("incompatible_charging_battery_icon")
- // TODO(b/293585143): Tracking Bug
- val INSTANT_TETHER = releasedFlag("instant_tether")
-
- // TODO(b/294588085): Tracking Bug
- val WIFI_SECONDARY_NETWORKS = releasedFlag("wifi_secondary_networks")
-
// TODO(b/290676905): Tracking Bug
val NEW_SHADE_CARRIER_GROUP_MOBILE_ICONS = releasedFlag("new_shade_carrier_group_mobile_icons")
@@ -233,9 +224,6 @@
// TODO(b/254512697): Tracking Bug
val MEDIA_TAP_TO_TRANSFER = releasedFlag("media_tap_to_transfer")
- // TODO(b/254512502): Tracking Bug
- val MEDIA_SESSION_ACTIONS = unreleasedFlag("media_session_actions")
-
// TODO(b/254512654): Tracking Bug
@JvmField val DREAM_MEDIA_COMPLICATION = unreleasedFlag("dream_media_complication")
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt
index e8e1dd4..7ecacdc 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt
@@ -18,20 +18,20 @@
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.inputdevice.tutorial.domain.interactor.TutorialSchedulerInteractor
+import com.android.systemui.inputdevice.tutorial.ui.TutorialNotificationCoordinator
import com.android.systemui.shared.Flags.newTouchpadGesturesTutorial
import dagger.Lazy
import javax.inject.Inject
-/** A [CoreStartable] to launch a scheduler for keyboard and touchpad education */
+/** A [CoreStartable] to launch a scheduler for keyboard and touchpad tutorial notification */
@SysUISingleton
class KeyboardTouchpadTutorialCoreStartable
@Inject
-constructor(private val tutorialSchedulerInteractor: Lazy<TutorialSchedulerInteractor>) :
+constructor(private val tutorialNotificationCoordinator: Lazy<TutorialNotificationCoordinator>) :
CoreStartable {
override fun start() {
if (newTouchpadGesturesTutorial()) {
- tutorialSchedulerInteractor.get().start()
+ tutorialNotificationCoordinator.get().start()
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt
index a8d7dad..cfc913f 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt
@@ -17,9 +17,7 @@
package com.android.systemui.inputdevice.tutorial.domain.interactor
import android.os.SystemProperties
-import android.util.Log
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType
import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.KEYBOARD
import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.TOUCHPAD
@@ -31,23 +29,22 @@
import javax.inject.Inject
import kotlin.time.Duration.Companion.hours
import kotlin.time.toKotlinDuration
-import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
-import kotlinx.coroutines.launch
/**
- * When the first time a keyboard or touchpad is connected, wait for [LAUNCH_DELAY], then launch the
- * tutorial as soon as there's a connected device
+ * When the first time a keyboard or touchpad is connected, wait for [LAUNCH_DELAY], and as soon as
+ * there's a connected device, show a notification to launch the tutorial.
*/
@SysUISingleton
class TutorialSchedulerInteractor
@Inject
constructor(
- @Background private val backgroundScope: CoroutineScope,
keyboardRepository: KeyboardRepository,
touchpadRepository: TouchpadRepository,
private val repo: TutorialSchedulerRepository
@@ -58,17 +55,6 @@
TOUCHPAD to touchpadRepository.isAnyTouchpadConnected
)
- fun start() {
- backgroundScope.launch {
- // Merging two flows to ensure that launch tutorial is launched consecutively in order
- // to avoid race condition
- merge(touchpadScheduleFlow, keyboardScheduleFlow).collect {
- val tutorialType = resolveTutorialType(it)
- launchTutorial(tutorialType)
- }
- }
- }
-
private val touchpadScheduleFlow = flow {
if (!repo.isLaunched(TOUCHPAD)) {
schedule(TOUCHPAD)
@@ -95,14 +81,19 @@
private suspend fun waitForDeviceConnection(deviceType: DeviceType) =
isAnyDeviceConnected[deviceType]!!.filter { it }.first()
- private suspend fun launchTutorial(tutorialType: TutorialType) {
- if (tutorialType == TutorialType.KEYBOARD || tutorialType == TutorialType.BOTH)
- repo.updateLaunchTime(KEYBOARD, Instant.now())
- if (tutorialType == TutorialType.TOUCHPAD || tutorialType == TutorialType.BOTH)
- repo.updateLaunchTime(TOUCHPAD, Instant.now())
- // TODO: launch tutorial
- Log.d(TAG, "Launch tutorial for $tutorialType")
- }
+ // Merging two flows ensures that tutorial is launched consecutively to avoid race condition
+ val tutorials: Flow<TutorialType> =
+ merge(touchpadScheduleFlow, keyboardScheduleFlow).map {
+ val tutorialType = resolveTutorialType(it)
+
+ // TODO: notifying time is not oobe launching time - move these updates into oobe
+ if (tutorialType == TutorialType.KEYBOARD || tutorialType == TutorialType.BOTH)
+ repo.updateLaunchTime(KEYBOARD, Instant.now())
+ if (tutorialType == TutorialType.TOUCHPAD || tutorialType == TutorialType.BOTH)
+ repo.updateLaunchTime(TOUCHPAD, Instant.now())
+
+ tutorialType
+ }
private suspend fun resolveTutorialType(deviceType: DeviceType): TutorialType {
// Resolve the type of tutorial depending on which device are connected when the tutorial is
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/TutorialNotificationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/TutorialNotificationCoordinator.kt
new file mode 100644
index 0000000..5d9dda3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/TutorialNotificationCoordinator.kt
@@ -0,0 +1,146 @@
+/*
+ * 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.inputdevice.tutorial.ui
+
+import android.app.Notification
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import androidx.core.app.NotificationCompat
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.inputdevice.tutorial.domain.interactor.TutorialSchedulerInteractor
+import com.android.systemui.inputdevice.tutorial.domain.interactor.TutorialSchedulerInteractor.Companion.TAG
+import com.android.systemui.inputdevice.tutorial.domain.interactor.TutorialSchedulerInteractor.TutorialType
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_BOTH
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEY
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEYBOARD
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_TOUCHPAD
+import com.android.systemui.res.R
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+
+/** When the scheduler is due, show a notification to launch tutorial */
+@SysUISingleton
+class TutorialNotificationCoordinator
+@Inject
+constructor(
+ @Background private val backgroundScope: CoroutineScope,
+ @Application private val context: Context,
+ private val tutorialSchedulerInteractor: TutorialSchedulerInteractor,
+ private val notificationManager: NotificationManager
+) {
+ fun start() {
+ backgroundScope.launch {
+ tutorialSchedulerInteractor.tutorials.collect { showNotification(it) }
+ }
+ }
+
+ // By sharing the same tag and id, we update the content of existing notification instead of
+ // creating multiple notifications
+ private fun showNotification(tutorialType: TutorialType) {
+ if (tutorialType == TutorialType.NONE) return
+
+ if (notificationManager.getNotificationChannel(CHANNEL_ID) == null)
+ createNotificationChannel()
+
+ // Replace "System UI" app name with "Android System"
+ val extras = Bundle()
+ extras.putString(
+ Notification.EXTRA_SUBSTITUTE_APP_NAME,
+ context.getString(com.android.internal.R.string.android_system_label)
+ )
+
+ val info = getNotificationInfo(tutorialType)!!
+ val notification =
+ NotificationCompat.Builder(context, CHANNEL_ID)
+ .setSmallIcon(R.drawable.ic_settings)
+ .setContentTitle(info.title)
+ .setContentText(info.text)
+ .setContentIntent(createPendingIntent(info.type))
+ .setPriority(NotificationCompat.PRIORITY_DEFAULT)
+ .setAutoCancel(true)
+ .addExtras(extras)
+ .build()
+
+ notificationManager.notify(TAG, NOTIFICATION_ID, notification)
+ }
+
+ private fun createNotificationChannel() {
+ val channel =
+ NotificationChannel(
+ CHANNEL_ID,
+ context.getString(com.android.internal.R.string.android_system_label),
+ NotificationManager.IMPORTANCE_DEFAULT
+ )
+ notificationManager.createNotificationChannel(channel)
+ }
+
+ private fun createPendingIntent(tutorialType: String): PendingIntent {
+ val intent =
+ Intent(context, KeyboardTouchpadTutorialActivity::class.java).apply {
+ putExtra(INTENT_TUTORIAL_TYPE_KEY, tutorialType)
+ flags = Intent.FLAG_ACTIVITY_NEW_TASK
+ }
+ return PendingIntent.getActivity(
+ context,
+ /* requestCode= */ 0,
+ intent,
+ PendingIntent.FLAG_IMMUTABLE
+ )
+ }
+
+ private data class NotificationInfo(val title: String, val text: String, val type: String)
+
+ private fun getNotificationInfo(tutorialType: TutorialType): NotificationInfo? =
+ when (tutorialType) {
+ TutorialType.KEYBOARD ->
+ NotificationInfo(
+ context.getString(R.string.launch_keyboard_tutorial_notification_title),
+ context.getString(R.string.launch_keyboard_tutorial_notification_content),
+ INTENT_TUTORIAL_TYPE_KEYBOARD
+ )
+ TutorialType.TOUCHPAD ->
+ NotificationInfo(
+ context.getString(R.string.launch_touchpad_tutorial_notification_title),
+ context.getString(R.string.launch_touchpad_tutorial_notification_content),
+ INTENT_TUTORIAL_TYPE_TOUCHPAD
+ )
+ TutorialType.BOTH ->
+ NotificationInfo(
+ context.getString(
+ R.string.launch_keyboard_touchpad_tutorial_notification_title
+ ),
+ context.getString(
+ R.string.launch_keyboard_touchpad_tutorial_notification_content
+ ),
+ INTENT_TUTORIAL_TYPE_BOTH
+ )
+ TutorialType.NONE -> null
+ }
+
+ companion object {
+ private const val CHANNEL_ID = "TutorialSchedulerNotificationChannel"
+ private const val NOTIFICATION_ID = 5566
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt
index 8debe79..1adc285 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt
@@ -54,6 +54,7 @@
const val INTENT_TUTORIAL_TYPE_KEY = "tutorial_type"
const val INTENT_TUTORIAL_TYPE_TOUCHPAD = "touchpad"
const val INTENT_TUTORIAL_TYPE_KEYBOARD = "keyboard"
+ const val INTENT_TUTORIAL_TYPE_BOTH = "both"
}
private val vm by
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 1bc91ca..67625d0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -81,6 +81,7 @@
import com.android.systemui.keyguard.domain.interactor.KeyguardDismissInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardEnabledInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardStateCallbackInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardWakeDirectlyToGoneInteractor;
import com.android.systemui.keyguard.ui.binder.KeyguardSurfaceBehindParamsApplier;
import com.android.systemui.keyguard.ui.binder.KeyguardSurfaceBehindViewBinder;
@@ -126,6 +127,7 @@
private final Lazy<DeviceEntryInteractor> mDeviceEntryInteractorLazy;
private final Executor mMainExecutor;
private final Lazy<KeyguardStateCallbackStartable> mKeyguardStateCallbackStartableLazy;
+ private final KeyguardStateCallbackInteractor mKeyguardStateCallbackInteractor;
private static RemoteAnimationTarget[] wrap(TransitionInfo info, boolean wallpapers,
SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap,
@@ -350,7 +352,8 @@
Lazy<KeyguardStateCallbackStartable> keyguardStateCallbackStartableLazy,
KeyguardWakeDirectlyToGoneInteractor keyguardWakeDirectlyToGoneInteractor,
KeyguardDismissInteractor keyguardDismissInteractor,
- Lazy<DeviceEntryInteractor> deviceEntryInteractorLazy) {
+ Lazy<DeviceEntryInteractor> deviceEntryInteractorLazy,
+ KeyguardStateCallbackInteractor keyguardStateCallbackInteractor) {
super();
mKeyguardViewMediator = keyguardViewMediator;
mKeyguardLifecyclesDispatcher = keyguardLifecyclesDispatcher;
@@ -363,6 +366,7 @@
mSceneInteractorLazy = sceneInteractorLazy;
mMainExecutor = mainExecutor;
mKeyguardStateCallbackStartableLazy = keyguardStateCallbackStartableLazy;
+ mKeyguardStateCallbackInteractor = keyguardStateCallbackInteractor;
mDeviceEntryInteractorLazy = deviceEntryInteractorLazy;
if (KeyguardWmStateRefactor.isEnabled()) {
@@ -455,6 +459,8 @@
checkPermission();
if (SceneContainerFlag.isEnabled()) {
mKeyguardStateCallbackStartableLazy.get().addCallback(callback);
+ } else if (KeyguardWmStateRefactor.isEnabled()) {
+ mKeyguardStateCallbackInteractor.addCallback(callback);
} else {
mKeyguardViewMediator.addStateMonitorCallback(callback);
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index d38c952..3b1569d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -2288,6 +2288,10 @@
}
private void updateInputRestrictedLocked() {
+ if (KeyguardWmStateRefactor.isEnabled()) {
+ return;
+ }
+
boolean inputRestricted = isInputRestricted();
if (mInputRestricted != inputRestricted) {
mInputRestricted = inputRestricted;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index a43bfd3..8a3d017 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -63,6 +63,7 @@
import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLogger;
import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancesMetricsLoggerImpl;
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransitionModule;
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordancesCombinedViewModelModule;
import com.android.systemui.log.SessionTracker;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.process.ProcessWrapper;
@@ -111,6 +112,7 @@
DeviceEntryIconTransitionModule.class,
FalsingModule.class,
KeyguardDataQuickAffordanceModule.class,
+ KeyguardQuickAffordancesCombinedViewModelModule.class,
KeyguardRepositoryModule.class,
DeviceEntryFaceAuthModule.class,
KeyguardDisplayModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt
index 7087752..ec52055 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt
@@ -101,7 +101,7 @@
secureSettings
.observerFlow(
names = arrayOf(Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK),
- userId = UserHandle.USER_SYSTEM,
+ userId = UserHandle.USER_ALL,
)
.onStart { emit(Unit) } // Forces an initial update.
.map { withContext(backgroundDispatcher) { getClockSize() } }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepository.kt
index a1e4af5..b67fd4b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardSmartspaceRepository.kt
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.data.repository
import android.content.Context
+import android.os.UserHandle
import android.provider.Settings
import android.view.View
import com.android.systemui.dagger.SysUISingleton
@@ -37,6 +38,7 @@
interface KeyguardSmartspaceRepository {
val bcSmartspaceVisibility: StateFlow<Int>
val isWeatherEnabled: StateFlow<Boolean>
+
fun setBcSmartspaceVisibility(visibility: Int)
}
@@ -55,7 +57,7 @@
secureSettings
.observerFlow(
names = arrayOf(Settings.Secure.LOCK_SCREEN_WEATHER_ENABLED),
- userId = userTracker.userId,
+ userId = UserHandle.USER_ALL,
)
.onStart { emit(Unit) }
.map { getLockscreenWeatherEnabled() }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
index db5a63b..58c8a04 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGoneTransitionInteractor.kt
@@ -73,7 +73,7 @@
if (SceneContainerFlag.isEnabled) return
listenForGoneToAodOrDozing()
listenForGoneToDreaming()
- listenForGoneToLockscreenOrHub()
+ listenForGoneToLockscreenOrHubOrOccluded()
listenForGoneToOccluded()
listenForGoneToDreamingLockscreenHosted()
}
@@ -89,22 +89,19 @@
*/
private fun listenForGoneToOccluded() {
scope.launch("$TAG#listenForGoneToOccluded") {
- keyguardInteractor.showDismissibleKeyguard
- .filterRelevantKeyguardState()
- .sample(keyguardInteractor.isKeyguardOccluded, ::Pair)
- .collect { (_, isKeyguardOccluded) ->
- if (isKeyguardOccluded) {
- startTransitionTo(
- KeyguardState.OCCLUDED,
- ownerReason = "Dismissible keyguard with occlusion"
- )
- }
+ keyguardInteractor.showDismissibleKeyguard.filterRelevantKeyguardState().collect {
+ if (keyguardInteractor.isKeyguardOccluded.value) {
+ startTransitionTo(
+ KeyguardState.OCCLUDED,
+ ownerReason = "Dismissible keyguard with occlusion"
+ )
}
+ }
}
}
// Primarily for when the user chooses to lock down the device
- private fun listenForGoneToLockscreenOrHub() {
+ private fun listenForGoneToLockscreenOrHubOrOccluded() {
if (KeyguardWmStateRefactor.isEnabled) {
scope.launch("$TAG#listenForGoneToLockscreenOrHub") {
biometricSettingsRepository.isCurrentUserInLockdown
@@ -137,7 +134,7 @@
}
}
} else {
- scope.launch("$TAG#listenForGoneToLockscreenOrHub") {
+ scope.launch("$TAG#listenForGoneToLockscreenOrHubOrOccluded") {
keyguardInteractor.isKeyguardShowing
.filterRelevantKeyguardStateAnd { isKeyguardShowing -> isKeyguardShowing }
.sample(communalSceneInteractor.isIdleOnCommunalNotEditMode, ::Pair)
@@ -145,6 +142,8 @@
val to =
if (isIdleOnCommunal) {
KeyguardState.GLANCEABLE_HUB
+ } else if (keyguardInteractor.isKeyguardOccluded.value) {
+ KeyguardState.OCCLUDED
} else {
KeyguardState.LOCKSCREEN
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardStateCallbackInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardStateCallbackInteractor.kt
new file mode 100644
index 0000000..420fbd4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardStateCallbackInteractor.kt
@@ -0,0 +1,93 @@
+/*
+ * 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.keyguard.domain.interactor
+
+import android.os.DeadObjectException
+import android.os.RemoteException
+import com.android.internal.policy.IKeyguardStateCallback
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.keyguard.KeyguardWmStateRefactor
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.user.domain.interactor.SelectedUserInteractor
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import javax.inject.Inject
+
+/**
+ * Updates KeyguardStateCallbacks provided to KeyguardService with KeyguardTransitionInteractor
+ * state.
+ *
+ * This borrows heavily from [KeyguardStateCallbackStartable], which requires Flexiglass. This class
+ * can be removed after Flexiglass launches.
+ */
+@SysUISingleton
+class KeyguardStateCallbackInteractor
+@Inject
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
+ private val selectedUserInteractor: SelectedUserInteractor,
+ private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
+) : CoreStartable {
+ private val callbacks = mutableListOf<IKeyguardStateCallback>()
+
+ override fun start() {
+ if (!KeyguardWmStateRefactor.isEnabled || SceneContainerFlag.isEnabled) {
+ return
+ }
+
+ applicationScope.launch {
+ combine(
+ selectedUserInteractor.selectedUser,
+ keyguardTransitionInteractor.currentKeyguardState,
+ ::Pair
+ ).collectLatest { (selectedUser, currentState) ->
+ val iterator = callbacks.iterator()
+ withContext(backgroundDispatcher) {
+ while (iterator.hasNext()) {
+ val callback = iterator.next()
+ try {
+ callback.onShowingStateChanged(
+ currentState != KeyguardState.GONE,
+ selectedUser
+ )
+ callback.onInputRestrictedStateChanged(
+ currentState != KeyguardState.GONE)
+ } catch (e: RemoteException) {
+ if (e is DeadObjectException) {
+ iterator.remove()
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ fun addCallback(callback: IKeyguardStateCallback) {
+ KeyguardWmStateRefactor.isUnexpectedlyInLegacyMode()
+ callbacks.add(callback)
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
index d9c48fa..25b8fd3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
@@ -29,6 +29,7 @@
private val auditLogger: KeyguardTransitionAuditLogger,
private val bootInteractor: KeyguardTransitionBootInteractor,
private val statusBarDisableFlagsInteractor: StatusBarDisableFlagsInteractor,
+ private val keyguardStateCallbackInteractor: KeyguardStateCallbackInteractor,
) : CoreStartable {
override fun start() {
@@ -55,6 +56,7 @@
auditLogger.start()
bootInteractor.start()
statusBarDisableFlagsInteractor.start()
+ keyguardStateCallbackInteractor.start()
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StatusBarDisableFlagsInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StatusBarDisableFlagsInteractor.kt
index e00e33d..43aab35 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StatusBarDisableFlagsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StatusBarDisableFlagsInteractor.kt
@@ -39,12 +39,14 @@
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.power.shared.model.WakefulnessModel
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -75,62 +77,66 @@
private val disableToken: IBinder = Binder()
private val disableFlagsForUserId =
- combine(
- selectedUserInteractor.selectedUser,
- keyguardTransitionInteractor.startedKeyguardTransitionStep.map { it.to },
- deviceConfigInteractor.property(
- namespace = DeviceConfig.NAMESPACE_SYSTEMUI,
- name = SystemUiDeviceConfigFlags.NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN,
- default = true,
- ),
- navigationInteractor.isGesturalMode,
- authenticationInteractor.authenticationMethod,
- powerInteractor.detailedWakefulness,
- ) { values ->
- val selectedUserId = values[0] as Int
- val startedState = values[1] as KeyguardState
- val isShowHomeOverLockscreen = values[2] as Boolean
- val isGesturalMode = values[3] as Boolean
- val authenticationMethod = values[4] as AuthenticationMethodModel
- val wakefulnessModel = values[5] as WakefulnessModel
- val isOccluded = startedState == KeyguardState.OCCLUDED
+ if (!KeyguardWmStateRefactor.isEnabled || SceneContainerFlag.isEnabled) {
+ flowOf(Pair(0, StatusBarManager.DISABLE_NONE))
+ } else {
+ combine(
+ selectedUserInteractor.selectedUser,
+ keyguardTransitionInteractor.startedKeyguardTransitionStep.map { it.to },
+ deviceConfigInteractor.property(
+ namespace = DeviceConfig.NAMESPACE_SYSTEMUI,
+ name = SystemUiDeviceConfigFlags.NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN,
+ default = true,
+ ),
+ navigationInteractor.isGesturalMode,
+ authenticationInteractor.authenticationMethod,
+ powerInteractor.detailedWakefulness,
+ ) { values ->
+ val selectedUserId = values[0] as Int
+ val startedState = values[1] as KeyguardState
+ val isShowHomeOverLockscreen = values[2] as Boolean
+ val isGesturalMode = values[3] as Boolean
+ val authenticationMethod = values[4] as AuthenticationMethodModel
+ val wakefulnessModel = values[5] as WakefulnessModel
+ val isOccluded = startedState == KeyguardState.OCCLUDED
- val hideHomeAndRecentsForBouncer =
- startedState == KeyguardState.PRIMARY_BOUNCER ||
- startedState == KeyguardState.ALTERNATE_BOUNCER
- val isKeyguardShowing = startedState != KeyguardState.GONE
- val isPowerGestureIntercepted =
- with(wakefulnessModel) {
- isAwake() &&
- powerButtonLaunchGestureTriggered &&
- lastSleepReason == WakeSleepReason.POWER_BUTTON
+ val hideHomeAndRecentsForBouncer =
+ startedState == KeyguardState.PRIMARY_BOUNCER ||
+ startedState == KeyguardState.ALTERNATE_BOUNCER
+ val isKeyguardShowing = startedState != KeyguardState.GONE
+ val isPowerGestureIntercepted =
+ with(wakefulnessModel) {
+ isAwake() &&
+ powerButtonLaunchGestureTriggered &&
+ lastSleepReason == WakeSleepReason.POWER_BUTTON
+ }
+
+ var flags = StatusBarManager.DISABLE_NONE
+
+ if (hideHomeAndRecentsForBouncer || (isKeyguardShowing && !isOccluded)) {
+ if (!isShowHomeOverLockscreen || !isGesturalMode) {
+ flags = flags or StatusBarManager.DISABLE_HOME
+ }
+ flags = flags or StatusBarManager.DISABLE_RECENT
}
- var flags = StatusBarManager.DISABLE_NONE
-
- if (hideHomeAndRecentsForBouncer || (isKeyguardShowing && !isOccluded)) {
- if (!isShowHomeOverLockscreen || !isGesturalMode) {
- flags = flags or StatusBarManager.DISABLE_HOME
+ if (
+ isPowerGestureIntercepted &&
+ isOccluded &&
+ authenticationMethod.isSecure &&
+ deviceEntryFaceAuthInteractor.isFaceAuthEnabledAndEnrolled()
+ ) {
+ flags = flags or StatusBarManager.DISABLE_RECENT
}
- flags = flags or StatusBarManager.DISABLE_RECENT
- }
- if (
- isPowerGestureIntercepted &&
- isOccluded &&
- authenticationMethod.isSecure &&
- deviceEntryFaceAuthInteractor.isFaceAuthEnabledAndEnrolled()
- ) {
- flags = flags or StatusBarManager.DISABLE_RECENT
+ selectedUserId to flags
}
-
- selectedUserId to flags
- }
- .distinctUntilChanged()
+ .distinctUntilChanged()
+ }
@SuppressLint("WrongConstant", "NonInjectedService")
override fun start() {
- if (!KeyguardWmStateRefactor.isEnabled) {
+ if (!KeyguardWmStateRefactor.isEnabled || SceneContainerFlag.isEnabled) {
return
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
index 91a7f7f..7696273 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
@@ -42,6 +42,7 @@
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerWindowViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.log.LongPressHandlingViewLogger
import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scrim.ScrimView
@@ -191,6 +192,7 @@
optionallyAddUdfpsViews(
view = view,
+ logger = alternateBouncerDependencies.logger,
udfpsIconViewModel = alternateBouncerDependencies.udfpsIconViewModel,
udfpsA11yOverlayViewModel =
alternateBouncerDependencies.udfpsAccessibilityOverlayViewModel,
@@ -248,6 +250,7 @@
private fun optionallyAddUdfpsViews(
view: ConstraintLayout,
+ logger: LongPressHandlingViewLogger,
udfpsIconViewModel: AlternateBouncerUdfpsIconViewModel,
udfpsA11yOverlayViewModel: Lazy<AlternateBouncerUdfpsAccessibilityOverlayViewModel>,
) {
@@ -276,7 +279,7 @@
var udfpsView = view.getViewById(udfpsViewId)
if (udfpsView == null) {
udfpsView =
- DeviceEntryIconView(view.context, null).apply {
+ DeviceEntryIconView(view.context, null, logger = logger).apply {
id = udfpsViewId
contentDescription =
context.resources.getString(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
index 4d6577c..b951b73 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
@@ -19,6 +19,7 @@
import android.annotation.SuppressLint
import android.content.res.ColorStateList
+import android.util.Log
import android.util.StateSet
import android.view.HapticFeedbackConstants
import android.view.View
@@ -83,6 +84,11 @@
if (
!isA11yAction && falsingManager.isFalseLongTap(FalsingManager.LOW_PENALTY)
) {
+ Log.d(
+ TAG,
+ "Long press rejected because it is not a11yAction " +
+ "and it is a falseLongTap"
+ )
return
}
vibratorHelper.performHapticFeedback(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
index 28a17ef..27dd18d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
@@ -93,7 +93,7 @@
val configurationBasedDimensions = MutableStateFlow(loadFromResources(view))
val disposableHandle =
view.repeatWhenAttached {
- repeatOnLifecycle(Lifecycle.State.CREATED) {
+ repeatOnLifecycle(Lifecycle.State.STARTED) {
launch {
viewModel.collect { buttonModel ->
updateButton(
@@ -141,6 +141,7 @@
viewModel: KeyguardQuickAffordanceViewModel,
messageDisplayer: (Int) -> Unit,
) {
+ logger.logUpdate(viewModel)
if (!viewModel.isVisible) {
view.isInvisible = true
return
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
index 7899971..5bb7b64 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
@@ -22,7 +22,6 @@
import android.annotation.SuppressLint
import android.graphics.Point
import android.graphics.Rect
-import android.os.VibrationAttributes
import android.util.Log
import android.view.HapticFeedbackConstants
import android.view.View
@@ -41,6 +40,7 @@
import com.android.app.tracing.coroutines.launch
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF_SHOW_AOD
+import com.android.keyguard.AuthInteractionProperties
import com.android.systemui.Flags.msdlFeedback
import com.android.systemui.Flags.newAodTransition
import com.android.systemui.common.shared.model.Icon
@@ -82,7 +82,6 @@
import com.android.systemui.util.ui.stopAnimating
import com.android.systemui.util.ui.value
import com.google.android.msdl.data.model.MSDLToken
-import com.google.android.msdl.domain.InteractionProperties
import com.google.android.msdl.domain.MSDLPlayer
import kotlin.math.min
import kotlinx.coroutines.CoroutineDispatcher
@@ -358,14 +357,10 @@
launch {
deviceEntryHapticsInteractor.playSuccessHaptic.collect {
if (msdlFeedback()) {
- val properties =
- object : InteractionProperties {
- override val vibrationAttributes: VibrationAttributes =
- VibrationAttributes.createForUsage(
- VibrationAttributes.USAGE_HARDWARE_FEEDBACK
- )
- }
- msdlPlayer?.playToken(MSDLToken.UNLOCK, properties)
+ msdlPlayer?.playToken(
+ MSDLToken.UNLOCK,
+ authInteractionProperties
+ )
} else {
vibratorHelper.performHapticFeedback(
view,
@@ -378,14 +373,10 @@
launch {
deviceEntryHapticsInteractor.playErrorHaptic.collect {
if (msdlFeedback()) {
- val properties =
- object : InteractionProperties {
- override val vibrationAttributes: VibrationAttributes =
- VibrationAttributes.createForUsage(
- VibrationAttributes.USAGE_HARDWARE_FEEDBACK
- )
- }
- msdlPlayer?.playToken(MSDLToken.FAILURE, properties)
+ msdlPlayer?.playToken(
+ MSDLToken.FAILURE,
+ authInteractionProperties
+ )
} else {
vibratorHelper.performHapticFeedback(
view,
@@ -660,6 +651,7 @@
private val lockIcon = R.id.lock_icon_view
private val deviceEntryIcon = R.id.device_entry_icon_view
private val nsslPlaceholderId = R.id.nssl_placeholder
+ private val authInteractionProperties = AuthInteractionProperties()
private const val ID = "occluding_app_device_entry_unlock_msg"
private const val AOD_ICONS_APPEAR_DURATION: Long = 200
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt
index a6108c4..075a1d2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardRemotePreviewManager.kt
@@ -26,7 +26,6 @@
import android.util.Log
import androidx.annotation.VisibleForTesting
import com.android.app.tracing.coroutines.runBlocking
-import com.android.systemui.Flags
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
@@ -67,11 +66,7 @@
var observer: PreviewLifecycleObserver? = null
return try {
val renderer =
- if (Flags.lockscreenPreviewRendererCreateOnMainThread()) {
- runBlocking("$TAG#previewRendererFactory.create", mainDispatcher) {
- previewRendererFactory.create(request)
- }
- } else {
+ runBlocking("$TAG#previewRendererFactory.create", mainDispatcher) {
previewRendererFactory.create(request)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt
index 3e6d5da..8d2e939 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt
@@ -23,6 +23,7 @@
import android.util.StateSet
import android.view.Gravity
import android.view.View
+import android.view.ViewConfiguration
import android.view.ViewGroup
import android.view.accessibility.AccessibilityNodeInfo
import android.widget.FrameLayout
@@ -31,6 +32,7 @@
import com.airbnb.lottie.LottieCompositionFactory
import com.airbnb.lottie.LottieDrawable
import com.android.systemui.common.ui.view.LongPressHandlingView
+import com.android.systemui.log.LongPressHandlingViewLogger
import com.android.systemui.res.R
class DeviceEntryIconView
@@ -39,8 +41,17 @@
context: Context,
attrs: AttributeSet?,
defStyleAttrs: Int = 0,
+ logger: LongPressHandlingViewLogger? = null,
) : FrameLayout(context, attrs, defStyleAttrs) {
- val longPressHandlingView: LongPressHandlingView = LongPressHandlingView(context, attrs)
+
+ val longPressHandlingView: LongPressHandlingView =
+ LongPressHandlingView(
+ context = context,
+ attrs = attrs,
+ longPressDuration = { ViewConfiguration.getLongPressTimeout().toLong() },
+ allowedTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(),
+ logger = logger,
+ )
val iconView: ImageView = ImageView(context, attrs).apply { id = R.id.device_entry_icon_fg }
val bgView: ImageView = ImageView(context, attrs).apply { id = R.id.device_entry_icon_bg }
val aodFpDrawable: LottieDrawable = LottieDrawable()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/BaseShortcutSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/BaseShortcutSection.kt
index a4137ac..8861c1e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/BaseShortcutSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/BaseShortcutSection.kt
@@ -4,10 +4,10 @@
import android.widget.ImageView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.res.ResourcesCompat
-import com.android.systemui.res.R
import com.android.systemui.animation.view.LaunchableImageView
import com.android.systemui.keyguard.shared.model.KeyguardSection
import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder
+import com.android.systemui.res.R
abstract class BaseShortcutSection : KeyguardSection() {
protected var leftShortcutHandle: KeyguardQuickAffordanceViewBinder.Binding? = null
@@ -15,7 +15,9 @@
override fun removeViews(constraintLayout: ConstraintLayout) {
leftShortcutHandle?.destroy()
+ leftShortcutHandle = null
rightShortcutHandle?.destroy()
+ rightShortcutHandle = null
constraintLayout.removeView(R.id.start_button)
constraintLayout.removeView(R.id.end_button)
}
@@ -75,6 +77,7 @@
}
constraintLayout.addView(view)
}
+
/**
* Defines equality as same class.
*
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
index 51230dd..782d37b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
@@ -42,6 +42,9 @@
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryBackgroundViewModel
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryForegroundViewModel
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LongPressHandlingViewLogger
+import com.android.systemui.log.dagger.LongPressTouchLog
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.res.R
import com.android.systemui.shade.NotificationPanelView
@@ -69,6 +72,7 @@
private val deviceEntryBackgroundViewModel: Lazy<DeviceEntryBackgroundViewModel>,
private val falsingManager: Lazy<FalsingManager>,
private val vibratorHelper: Lazy<VibratorHelper>,
+ @LongPressTouchLog private val logBuffer: LogBuffer,
) : KeyguardSection() {
private val deviceEntryIconViewId = R.id.device_entry_icon_view
private var disposableHandle: DisposableHandle? = null
@@ -88,7 +92,16 @@
val view =
if (DeviceEntryUdfpsRefactor.isEnabled) {
- DeviceEntryIconView(context, null).apply { id = deviceEntryIconViewId }
+ DeviceEntryIconView(
+ context,
+ null,
+ logger =
+ LongPressHandlingViewLogger(
+ logBuffer = logBuffer,
+ TAG
+ )
+ )
+ .apply { id = deviceEntryIconViewId }
} else {
// KeyguardBottomAreaRefactor.isEnabled or MigrateClocksToBlueprint.isEnabled
LockIconView(context, null).apply { id = R.id.lock_icon_view }
@@ -258,4 +271,8 @@
}
}
}
+
+ companion object {
+ private const val TAG = "DefaultDeviceEntrySection"
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
index e558033..6c6e14c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
@@ -33,16 +33,19 @@
import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder
import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition
import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordancesCombinedViewModel
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordancesCombinedViewModelModule.Companion.LOCKSCREEN_INSTANCE
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
import com.android.systemui.res.R
import com.android.systemui.statusbar.KeyguardIndicationController
import dagger.Lazy
import javax.inject.Inject
+import javax.inject.Named
class DefaultShortcutsSection
@Inject
constructor(
@Main private val resources: Resources,
+ @Named(LOCKSCREEN_INSTANCE)
private val keyguardQuickAffordancesCombinedViewModel:
KeyguardQuickAffordancesCombinedViewModel,
private val keyguardRootViewModel: KeyguardRootViewModel,
@@ -76,6 +79,7 @@
override fun bindData(constraintLayout: ConstraintLayout) {
if (KeyguardBottomAreaRefactor.isEnabled) {
+ leftShortcutHandle?.destroy()
leftShortcutHandle =
keyguardQuickAffordanceViewBinder.bind(
constraintLayout.requireViewById(R.id.start_button),
@@ -84,6 +88,7 @@
) {
indicationController.showTransientIndication(it)
}
+ rightShortcutHandle?.destroy()
rightShortcutHandle =
keyguardQuickAffordanceViewBinder.bind(
constraintLayout.requireViewById(R.id.end_button),
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerDependencies.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerDependencies.kt
index b432417..9f8e9c5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerDependencies.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerDependencies.kt
@@ -18,6 +18,9 @@
import com.android.systemui.deviceentry.ui.viewmodel.AlternateBouncerUdfpsAccessibilityOverlayViewModel
import com.android.systemui.keyguard.ui.SwipeUpAnywhereGestureHandler
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LongPressHandlingViewLogger
+import com.android.systemui.log.dagger.LongPressTouchLog
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.statusbar.gesture.TapGestureDetector
import dagger.Lazy
@@ -37,4 +40,11 @@
Lazy<AlternateBouncerUdfpsAccessibilityOverlayViewModel>,
val messageAreaViewModel: AlternateBouncerMessageAreaViewModel,
val powerInteractor: PowerInteractor,
-)
+ @LongPressTouchLog private val touchLogBuffer: LogBuffer,
+) {
+ val logger: LongPressHandlingViewLogger =
+ LongPressHandlingViewLogger(logBuffer = touchLogBuffer, TAG)
+ companion object {
+ private const val TAG = "AlternateBouncer"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
index 9f68210..a021de4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
@@ -43,23 +43,22 @@
val deviceEntryIconViewModel: DeviceEntryIconViewModel,
keyguardTransitionInteractor: KeyguardTransitionInteractor,
configurationInteractor: ConfigurationInteractor,
- lockscreenToAodTransitionViewModel: LockscreenToAodTransitionViewModel,
- aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel,
- goneToAodTransitionViewModel: GoneToAodTransitionViewModel,
- primaryBouncerToAodTransitionViewModel: PrimaryBouncerToAodTransitionViewModel,
- occludedToAodTransitionViewModel: OccludedToAodTransitionViewModel,
- occludedToLockscreenTransitionViewModel: OccludedToLockscreenTransitionViewModel,
- dreamingToLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel,
alternateBouncerToAodTransitionViewModel: AlternateBouncerToAodTransitionViewModel,
- goneToLockscreenTransitionViewModel: GoneToLockscreenTransitionViewModel,
- goneToDozingTransitionViewModel: GoneToDozingTransitionViewModel,
- primaryBouncerToDozingTransitionViewModel: PrimaryBouncerToDozingTransitionViewModel,
- lockscreenToDozingTransitionViewModel: LockscreenToDozingTransitionViewModel,
- dozingToLockscreenTransitionViewModel: DozingToLockscreenTransitionViewModel,
alternateBouncerToDozingTransitionViewModel: AlternateBouncerToDozingTransitionViewModel,
+ aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel,
+ dozingToLockscreenTransitionViewModel: DozingToLockscreenTransitionViewModel,
dreamingToAodTransitionViewModel: DreamingToAodTransitionViewModel,
- primaryBouncerToLockscreenTransitionViewModel: PrimaryBouncerToLockscreenTransitionViewModel,
+ dreamingToLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel,
+ goneToAodTransitionViewModel: GoneToAodTransitionViewModel,
+ goneToDozingTransitionViewModel: GoneToDozingTransitionViewModel,
+ goneToLockscreenTransitionViewModel: GoneToLockscreenTransitionViewModel,
+ lockscreenToAodTransitionViewModel: LockscreenToAodTransitionViewModel,
+ occludedToAodTransitionViewModel: OccludedToAodTransitionViewModel,
occludedToDozingTransitionViewModel: OccludedToDozingTransitionViewModel,
+ occludedToLockscreenTransitionViewModel: OccludedToLockscreenTransitionViewModel,
+ primaryBouncerToAodTransitionViewModel: PrimaryBouncerToAodTransitionViewModel,
+ primaryBouncerToDozingTransitionViewModel: PrimaryBouncerToDozingTransitionViewModel,
+ primaryBouncerToLockscreenTransitionViewModel: PrimaryBouncerToLockscreenTransitionViewModel,
) {
val color: Flow<Int> =
deviceEntryIconViewModel.useBackgroundProtection.flatMapLatest { useBackground ->
@@ -98,7 +97,6 @@
goneToLockscreenTransitionViewModel.deviceEntryBackgroundViewAlpha,
goneToDozingTransitionViewModel.deviceEntryBackgroundViewAlpha,
primaryBouncerToDozingTransitionViewModel.deviceEntryBackgroundViewAlpha,
- lockscreenToDozingTransitionViewModel.deviceEntryBackgroundViewAlpha,
dozingToLockscreenTransitionViewModel.deviceEntryBackgroundViewAlpha,
alternateBouncerToDozingTransitionViewModel.deviceEntryBackgroundViewAlpha,
dreamingToAodTransitionViewModel.deviceEntryBackgroundViewAlpha,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt
index 609b571d..ceae1b5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt
@@ -33,6 +33,7 @@
import com.android.systemui.res.R
import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf
import javax.inject.Inject
+import javax.inject.Named
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
@@ -50,6 +51,7 @@
keyguardBottomAreaViewModel: KeyguardBottomAreaViewModel,
private val burnInHelperWrapper: BurnInHelperWrapper,
burnInInteractor: BurnInInteractor,
+ @Named(KeyguardQuickAffordancesCombinedViewModelModule.Companion.LOCKSCREEN_INSTANCE)
shortcutsCombinedViewModel: KeyguardQuickAffordancesCombinedViewModel,
configurationInteractor: ConfigurationInteractor,
keyguardTransitionInteractor: KeyguardTransitionInteractor,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt
index 72740d5..7e13d22 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModel.kt
@@ -177,10 +177,16 @@
)
}
} else {
- button(
- KeyguardQuickAffordancePosition.BOTTOM_START,
- )
+ button(KeyguardQuickAffordancePosition.BOTTOM_START)
}
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue =
+ KeyguardQuickAffordanceViewModel(
+ slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId()
+ ),
+ )
/** An observable for the view-model of the "end button" quick affordance. */
val endButton: Flow<KeyguardQuickAffordanceViewModel> =
@@ -194,6 +200,14 @@
} else {
button(KeyguardQuickAffordancePosition.BOTTOM_END)
}
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue =
+ KeyguardQuickAffordanceViewModel(
+ slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId()
+ ),
+ )
/**
* Notifies that a slot with the given ID has been selected in the preview experience that is
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelModule.kt
new file mode 100644
index 0000000..fceacc9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelModule.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.keyguard.ui.viewmodel
+
+import com.android.systemui.dagger.SysUISingleton
+import dagger.Binds
+import dagger.Module
+import javax.inject.Named
+
+@Module
+interface KeyguardQuickAffordancesCombinedViewModelModule {
+ companion object {
+ const val LOCKSCREEN_INSTANCE = "lockscreen_instance"
+ }
+
+ @SysUISingleton
+ @Binds
+ @Named(LOCKSCREEN_INSTANCE)
+ fun provideKeyguardQuickAffordancesCombinedViewModel(
+ model: KeyguardQuickAffordancesCombinedViewModel
+ ): KeyguardQuickAffordancesCombinedViewModel
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt
index adb63b7..75b1b04 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt
@@ -17,7 +17,6 @@
package com.android.systemui.keyguard.ui.viewmodel
import android.content.res.Resources
-import com.android.compose.animation.scene.ContentKey
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.biometrics.AuthController
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
@@ -27,7 +26,6 @@
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.SceneContainerOcclusionInteractor
-import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
import dagger.assisted.AssistedFactory
@@ -42,7 +40,6 @@
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
@@ -103,17 +100,8 @@
}
}
- /**
- * Returns a flow that indicates whether lockscreen notifications should be rendered in the
- * given [contentKey].
- */
- fun areNotificationsVisible(contentKey: ContentKey): Flow<Boolean> {
- // `Scenes.NotificationsShade` renders its own separate notifications stack, so when it's
- // open we avoid rendering the lockscreen notifications stack.
- if (contentKey == Scenes.NotificationsShade) {
- return flowOf(false)
- }
-
+ /** Returns a flow that indicates whether lockscreen notifications should be rendered. */
+ fun areNotificationsVisible(): Flow<Boolean> {
return combine(
clockSize,
shadeInteractor.isShadeLayoutWide,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt
index 27a1f7a..d3eefca 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt
@@ -45,13 +45,7 @@
edge = Edge.create(from = LOCKSCREEN, to = DOZING),
)
- val lockscreenAlpha: Flow<Float> =
- transitionAnimation.sharedFlow(
- duration = 250.milliseconds,
- onStep = { 1 - it },
- onFinish = { 1f },
- onCancel = { 1f },
- )
+ val lockscreenAlpha: Flow<Float> = transitionAnimation.immediatelyTransitionTo(1f)
val shortcutsAlpha: Flow<Float> =
transitionAnimation.sharedFlow(
@@ -61,18 +55,16 @@
onCancel = { 1f },
)
- val deviceEntryBackgroundViewAlpha: Flow<Float> =
- transitionAnimation.immediatelyTransitionTo(0f)
-
override val deviceEntryParentViewAlpha: Flow<Float> =
deviceEntryUdfpsInteractor.isUdfpsEnrolledAndEnabled.flatMapLatest {
isUdfpsEnrolledAndEnabled ->
- transitionAnimation.immediatelyTransitionTo(
- if (isUdfpsEnrolledAndEnabled) {
- 1f
- } else {
- 0f
- }
- )
+ if (isUdfpsEnrolledAndEnabled) {
+ transitionAnimation.immediatelyTransitionTo(1f)
+ } else {
+ transitionAnimation.sharedFlow(
+ duration = 250.milliseconds,
+ onStep = { 1f - it },
+ )
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModel.kt
similarity index 96%
rename from packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneActionsViewModel.kt
rename to packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModel.kt
index 2819e61..dd47678 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModel.kt
@@ -28,7 +28,7 @@
import com.android.systemui.scene.shared.model.SceneFamilies
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.TransitionKeys.ToSplitShade
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.util.kotlin.filterValuesNotNull
@@ -40,13 +40,13 @@
import kotlinx.coroutines.flow.flowOf
/** Models UI state and handles user input for the lockscreen scene. */
-class LockscreenSceneActionsViewModel
+class LockscreenUserActionsViewModel
@AssistedInject
constructor(
private val deviceEntryInteractor: DeviceEntryInteractor,
private val communalInteractor: CommunalInteractor,
private val shadeInteractor: ShadeInteractor,
-) : SceneActionsViewModel() {
+) : UserActionsViewModel() {
override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
shadeInteractor.isShadeTouchable
@@ -119,6 +119,6 @@
@AssistedFactory
interface Factory {
- fun create(): LockscreenSceneActionsViewModel
+ fun create(): LockscreenUserActionsViewModel
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/log/LongPressHandlingViewLogger.kt b/packages/SystemUI/src/com/android/systemui/log/LongPressHandlingViewLogger.kt
new file mode 100644
index 0000000..4ff8118
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/LongPressHandlingViewLogger.kt
@@ -0,0 +1,80 @@
+/*
+ * 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.log
+
+import com.android.systemui.log.core.LogLevel.DEBUG
+import com.google.errorprone.annotations.CompileTimeConstant
+
+data class LongPressHandlingViewLogger
+constructor(
+ private val logBuffer: LogBuffer,
+ @CompileTimeConstant private val tag: String = "LongPressHandlingViewLogger"
+) {
+ fun schedulingLongPress(delay: Long) {
+ logBuffer.log(
+ tag,
+ DEBUG,
+ { long1 = delay },
+ { "on MotionEvent.Down: scheduling long press activation after $long1 ms" }
+ )
+ }
+
+ fun longPressTriggered() {
+ logBuffer.log(tag, DEBUG, "long press event detected and dispatched")
+ }
+
+ fun motionEventCancelled() {
+ logBuffer.log(tag, DEBUG, "Long press may be cancelled due to MotionEventModel.Cancel")
+ }
+
+ fun dispatchingSingleTap() {
+ logBuffer.log(tag, DEBUG, "Dispatching single tap instead of long press")
+ }
+
+ fun onUpEvent(distanceMoved: Float, touchSlop: Int, gestureDuration: Long) {
+ logBuffer.log(
+ tag,
+ DEBUG,
+ {
+ double1 = distanceMoved.toDouble()
+ int1 = touchSlop
+ long1 = gestureDuration
+ },
+ {
+ "on MotionEvent.Up: distanceMoved: $double1, " +
+ "allowedTouchSlop: $int1, " +
+ "eventDuration: $long1"
+ }
+ )
+ }
+
+ fun cancelingLongPressDueToTouchSlop(distanceMoved: Float, allowedTouchSlop: Int) {
+ logBuffer.log(
+ tag,
+ DEBUG,
+ {
+ double1 = distanceMoved.toDouble()
+ int1 = allowedTouchSlop
+ },
+ {
+ "on MotionEvent.Motion: May cancel long press due to movement: " +
+ "distanceMoved: $double1, " +
+ "allowedTouchSlop: $int1 "
+ }
+ )
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index ed76646..498c34c 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -382,16 +382,6 @@
return factory.create("MediaLog", 20);
}
- /**
- * Provides a buffer for media device changes
- */
- @Provides
- @SysUISingleton
- @MediaDeviceLog
- public static LogBuffer providesMediaDeviceLogBuffer(LogBufferFactory factory) {
- return factory.create("MediaDeviceLog", 50);
- }
-
/** Allows logging buffers to be tweaked via adb on debug builds but not on prod builds. */
@Provides
@SysUISingleton
@@ -584,7 +574,7 @@
@SysUISingleton
@KeyguardQuickAffordancesLog
public static LogBuffer provideKeyguardQuickAffordancesLogBuffer(LogBufferFactory factory) {
- return factory.create("KeyguardQuickAffordancesLog", 25);
+ return factory.create("KeyguardQuickAffordancesLog", 100);
}
/**
@@ -727,4 +717,12 @@
public static LogBuffer provideVolumeLogBuffer(LogBufferFactory factory) {
return factory.create("VolumeLog", 50);
}
+
+ /** Provides a {@link LogBuffer} for use by long touch event handlers. */
+ @Provides
+ @SysUISingleton
+ @LongPressTouchLog
+ public static LogBuffer providesLongPressTouchLog(LogBufferFactory factory) {
+ return factory.create("LongPressViewLog", 200);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/MediaDeviceLog.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/LongPressTouchLog.kt
similarity index 81%
rename from packages/SystemUI/src/com/android/systemui/log/dagger/MediaDeviceLog.kt
rename to packages/SystemUI/src/com/android/systemui/log/dagger/LongPressTouchLog.kt
index 06bd269..1163d74 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/MediaDeviceLog.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LongPressTouchLog.kt
@@ -16,11 +16,10 @@
package com.android.systemui.log.dagger
-import com.android.systemui.log.LogBuffer
import javax.inject.Qualifier
-/** A [LogBuffer] for [com.android.systemui.media.controls.domain.pipeline.MediaDeviceLogger] */
+/** Log buffer for logging touch/long press events */
@Qualifier
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
-annotation class MediaDeviceLog
+annotation class LongPressTouchLog
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
index 2089cce5..89a599a 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
@@ -16,19 +16,17 @@
package com.android.systemui.log.table
+import android.annotation.SuppressLint
import android.icu.text.SimpleDateFormat
import android.os.Trace
import com.android.systemui.Dumpable
import com.android.systemui.common.buffer.RingBuffer
-import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.log.LogcatEchoTracker
import com.android.systemui.log.core.LogLevel
import com.android.systemui.plugins.log.TableLogBufferBase
import com.android.systemui.util.time.SystemClock
import java.io.PrintWriter
import java.util.Locale
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
/**
* A logger that logs changes in table format.
@@ -75,13 +73,12 @@
*
* @param maxSize the maximum size of the buffer. Must be > 0.
*/
+@SuppressLint("DumpableNotRegistered") // Registered as dumpable in [TableLogBufferFactory]
class TableLogBuffer(
maxSize: Int,
private val name: String,
private val systemClock: SystemClock,
private val logcatEchoTracker: LogcatEchoTracker,
- @Background private val bgDispatcher: CoroutineDispatcher,
- private val coroutineScope: CoroutineScope,
private val localLogcat: LogProxy = LogProxyDefault(),
) : Dumpable, TableLogBufferBase {
init {
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
index ff523ae..425e674e 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
@@ -17,15 +17,11 @@
package com.android.systemui.log.table
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dump.DumpManager
import com.android.systemui.log.LogBufferHelper.Companion.adjustMaxSize
import com.android.systemui.log.LogcatEchoTracker
import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
@SysUISingleton
class TableLogBufferFactory
@@ -34,8 +30,6 @@
private val dumpManager: DumpManager,
private val systemClock: SystemClock,
private val logcatEchoTracker: LogcatEchoTracker,
- @Background private val bgDispatcher: CoroutineDispatcher,
- @Application private val coroutineScope: CoroutineScope,
) {
private val existingBuffers = mutableMapOf<String, TableLogBuffer>()
@@ -58,8 +52,6 @@
name,
systemClock,
logcatEchoTracker,
- bgDispatcher,
- coroutineScope,
)
dumpManager.registerTableLogBuffer(name, tableBuffer)
return tableBuffer
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt
index 24c57be..4ad437c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt
@@ -76,6 +76,7 @@
import com.android.systemui.media.controls.shared.model.MediaButton
import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.media.controls.shared.model.MediaDeviceData
+import com.android.systemui.media.controls.shared.model.MediaNotificationAction
import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
import com.android.systemui.media.controls.shared.model.SmartspaceMediaDataProvider
import com.android.systemui.media.controls.ui.view.MediaViewHolder
@@ -943,7 +944,7 @@
desc.subtitle,
desc.title,
artworkIcon,
- listOf(mediaAction),
+ listOf(),
listOf(0),
MediaButton(playOrPause = mediaAction),
packageName,
@@ -1074,13 +1075,13 @@
}
// Control buttons
- // If flag is enabled and controller has a PlaybackState, create actions from session info
+ // If controller has a PlaybackState, create actions from session info
// Otherwise, use the notification actions
- var actionIcons: List<MediaAction> = emptyList()
+ var actionIcons: List<MediaNotificationAction> = emptyList()
var actionsToShowCollapsed: List<Int> = emptyList()
val semanticActions = createActionsFromState(sbn.packageName, mediaController, sbn.user)
if (semanticActions == null) {
- val actions = createActionsFromNotification(context, activityStarter, sbn)
+ val actions = createActionsFromNotification(context, sbn)
actionIcons = actions.first
actionsToShowCollapsed = actions.second
}
@@ -1464,7 +1465,7 @@
val updated =
data.copy(
token = null,
- actions = actions,
+ actions = listOf(),
semanticActions = MediaButton(playOrPause = resumeAction),
actionsToShowInCompact = listOf(0),
active = false,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaActions.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaActions.kt
index bcf748e..f2825d0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaActions.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaActions.kt
@@ -33,6 +33,7 @@
import com.android.systemui.media.controls.shared.MediaControlDrawables
import com.android.systemui.media.controls.shared.model.MediaAction
import com.android.systemui.media.controls.shared.model.MediaButton
+import com.android.systemui.media.controls.shared.model.MediaNotificationAction
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.res.R
import com.android.systemui.statusbar.NotificationMediaManager.isConnectingState
@@ -217,11 +218,10 @@
/** Generate action buttons based on notification actions */
fun createActionsFromNotification(
context: Context,
- activityStarter: ActivityStarter,
sbn: StatusBarNotification
-): Pair<List<MediaAction>, List<Int>> {
+): Pair<List<MediaNotificationAction>, List<Int>> {
val notif = sbn.notification
- val actionIcons: MutableList<MediaAction> = ArrayList()
+ val actionIcons: MutableList<MediaNotificationAction> = ArrayList()
val actions = notif.actions
var actionsToShowCollapsed =
notif.extras.getIntArray(Notification.EXTRA_COMPACT_ACTIONS)?.toMutableList()
@@ -250,25 +250,6 @@
continue
}
- val runnable =
- action.actionIntent?.let { actionIntent ->
- Runnable {
- when {
- actionIntent.isActivity ->
- activityStarter.startPendingIntentDismissingKeyguard(
- action.actionIntent
- )
- action.isAuthenticationRequired ->
- activityStarter.dismissKeyguardThenExecute(
- { sendPendingIntent(action.actionIntent) },
- {},
- true
- )
- else -> sendPendingIntent(actionIntent)
- }
- }
- }
-
val themeText =
com.android.settingslib.Utils.getColorAttr(
context,
@@ -285,13 +266,53 @@
.setTint(themeText)
.loadDrawable(context)
- val mediaAction = MediaAction(mediaActionIcon, runnable, action.title, null)
+ val mediaAction =
+ MediaNotificationAction(
+ action.isAuthenticationRequired,
+ action.actionIntent,
+ mediaActionIcon,
+ action.title
+ )
actionIcons.add(mediaAction)
}
}
return Pair(actionIcons, actionsToShowCollapsed)
}
+/**
+ * Converts [MediaNotificationAction] list into [MediaAction] list
+ *
+ * @param actions list of [MediaNotificationAction]
+ * @param activityStarter starter for activities
+ * @return list of [MediaAction]
+ */
+fun getNotificationActions(
+ actions: List<MediaNotificationAction>,
+ activityStarter: ActivityStarter
+): List<MediaAction> {
+ return actions.map { action ->
+ val runnable =
+ action.actionIntent?.let { actionIntent ->
+ Runnable {
+ when {
+ actionIntent.isActivity ->
+ activityStarter.startPendingIntentDismissingKeyguard(
+ action.actionIntent
+ )
+ action.isAuthenticationRequired ->
+ activityStarter.dismissKeyguardThenExecute(
+ { sendPendingIntent(action.actionIntent) },
+ {},
+ true
+ )
+ else -> sendPendingIntent(actionIntent)
+ }
+ }
+ }
+ MediaAction(action.icon, runnable, action.contentDescription, background = null)
+ }
+}
+
private fun sendPendingIntent(intent: PendingIntent): Boolean {
return try {
intent.send(
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt
index f9fef8e..53cc15b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoader.kt
@@ -54,10 +54,10 @@
import com.android.systemui.media.controls.shared.model.MediaButton
import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.media.controls.shared.model.MediaDeviceData
+import com.android.systemui.media.controls.shared.model.MediaNotificationAction
import com.android.systemui.media.controls.util.MediaControllerFactory
import com.android.systemui.media.controls.util.MediaDataUtils
import com.android.systemui.media.controls.util.MediaFlags
-import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.res.R
import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState
import com.android.systemui.statusbar.notification.row.HybridGroupManager
@@ -80,7 +80,6 @@
@Application val context: Context,
@Main val mainDispatcher: CoroutineDispatcher,
@Background val backgroundScope: CoroutineScope,
- private val activityStarter: ActivityStarter,
private val mediaControllerFactory: MediaControllerFactory,
private val mediaFlags: MediaFlags,
private val imageLoader: ImageLoader,
@@ -209,15 +208,14 @@
val device: MediaDeviceData? = getDeviceInfoForRemoteCast(key, sbn)
// Control buttons
- // If flag is enabled and controller has a PlaybackState, create actions from session
- // info
+ // If controller has a PlaybackState, create actions from session info
// Otherwise, use the notification actions
- var actionIcons: List<MediaAction> = emptyList()
+ var actionIcons: List<MediaNotificationAction> = emptyList()
var actionsToShowCollapsed: List<Int> = emptyList()
val semanticActions = createActionsFromState(sbn.packageName, mediaController, sbn.user)
logD(TAG) { "Semantic actions: $semanticActions" }
if (semanticActions == null) {
- val actions = createActionsFromNotification(context, activityStarter, sbn)
+ val actions = createActionsFromNotification(context, sbn)
actionIcons = actions.first
actionsToShowCollapsed = actions.second
logD(TAG) { "[!!] Semantic actions: $semanticActions" }
@@ -329,7 +327,7 @@
artist = desc.subtitle,
song = desc.title,
artworkIcon = artworkIcon,
- actionIcons = listOf(mediaAction),
+ actionIcons = listOf(),
actionsToShowInCompact = listOf(0),
semanticActions = MediaButton(playOrPause = mediaAction),
token = token,
@@ -514,7 +512,7 @@
val artist: CharSequence?,
val song: CharSequence?,
val artworkIcon: Icon?,
- val actionIcons: List<MediaAction>,
+ val actionIcons: List<MediaNotificationAction>,
val actionsToShowInCompact: List<Int>,
val semanticActions: MediaButton?,
val token: MediaSession.Token?,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt
index 4555810..5f0a9f8 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt
@@ -71,12 +71,14 @@
import com.android.systemui.media.controls.domain.pipeline.MediaDataManager.Companion.isMediaNotification
import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
import com.android.systemui.media.controls.domain.resume.ResumeMediaBrowser
+import com.android.systemui.media.controls.shared.MediaLogger
import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_SOURCE
import com.android.systemui.media.controls.shared.model.EXTRA_VALUE_TRIGGER_PERIODIC
import com.android.systemui.media.controls.shared.model.MediaAction
import com.android.systemui.media.controls.shared.model.MediaButton
import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.media.controls.shared.model.MediaDeviceData
+import com.android.systemui.media.controls.shared.model.MediaNotificationAction
import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
import com.android.systemui.media.controls.shared.model.SmartspaceMediaDataProvider
import com.android.systemui.media.controls.ui.view.MediaViewHolder
@@ -149,6 +151,7 @@
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
private val mediaDataRepository: MediaDataRepository,
private val mediaDataLoader: dagger.Lazy<MediaDataLoader>,
+ private val mediaLogger: MediaLogger,
) : CoreStartable, BcSmartspaceDataPlugin.SmartspaceTargetListener {
companion object {
@@ -228,6 +231,7 @@
keyguardUpdateMonitor: KeyguardUpdateMonitor,
mediaDataRepository: MediaDataRepository,
mediaDataLoader: dagger.Lazy<MediaDataLoader>,
+ mediaLogger: MediaLogger,
) : this(
context,
applicationScope,
@@ -253,6 +257,7 @@
keyguardUpdateMonitor,
mediaDataRepository,
mediaDataLoader,
+ mediaLogger,
)
private val appChangeReceiver =
@@ -794,7 +799,7 @@
desc.subtitle,
desc.title,
artworkIcon,
- listOf(mediaAction),
+ listOf(),
listOf(0),
MediaButton(playOrPause = mediaAction),
packageName,
@@ -832,12 +837,48 @@
return@withContext
}
- val currentEntry = mediaDataRepository.mediaEntries.value[key]
- val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId()
- val createdTimestampMillis = currentEntry?.createdTimestampMillis ?: 0L
- val resumeAction: Runnable? = currentEntry?.resumeAction
- val hasCheckedForResume = currentEntry?.hasCheckedForResume == true
- val active = currentEntry?.active ?: true
+ val mediaController = mediaControllerFactory.create(result.token!!)
+ val oldEntry = mediaDataRepository.mediaEntries.value[key]
+ val instanceId = oldEntry?.instanceId ?: logger.getNewInstanceId()
+ val createdTimestampMillis = oldEntry?.createdTimestampMillis ?: 0L
+ val resumeAction: Runnable? = oldEntry?.resumeAction
+ val hasCheckedForResume = oldEntry?.hasCheckedForResume == true
+ val active = oldEntry?.active ?: true
+
+ val mediaData =
+ MediaData(
+ userId = sbn.normalizedUserId,
+ initialized = true,
+ app = result.appName,
+ appIcon = result.appIcon,
+ artist = result.artist,
+ song = result.song,
+ artwork = result.artworkIcon,
+ actions = result.actionIcons,
+ actionsToShowInCompact = result.actionsToShowInCompact,
+ semanticActions = result.semanticActions,
+ packageName = sbn.packageName,
+ token = result.token,
+ clickIntent = result.clickIntent,
+ device = result.device,
+ active = active,
+ resumeAction = resumeAction,
+ playbackLocation = result.playbackLocation,
+ notificationKey = key,
+ hasCheckedForResume = hasCheckedForResume,
+ isPlaying = result.isPlaying,
+ isClearable = !sbn.isOngoing,
+ lastActive = lastActive,
+ createdTimestampMillis = createdTimestampMillis,
+ instanceId = instanceId,
+ appUid = result.appUid,
+ isExplicit = result.isExplicit,
+ )
+
+ if (isSameMediaData(context, mediaController, mediaData, oldEntry)) {
+ mediaLogger.logDuplicateMediaNotification(key)
+ return@withContext
+ }
// We need to log the correct media added.
if (isNewlyActiveEntry) {
@@ -848,7 +889,7 @@
instanceId,
result.playbackLocation
)
- } else if (result.playbackLocation != currentEntry?.playbackLocation) {
+ } else if (result.playbackLocation != oldEntry?.playbackLocation) {
logger.logPlaybackLocationChange(
result.appUid,
sbn.packageName,
@@ -857,40 +898,7 @@
)
}
- withContext(mainDispatcher) {
- onMediaDataLoaded(
- key,
- oldKey,
- MediaData(
- userId = sbn.normalizedUserId,
- initialized = true,
- app = result.appName,
- appIcon = result.appIcon,
- artist = result.artist,
- song = result.song,
- artwork = result.artworkIcon,
- actions = result.actionIcons,
- actionsToShowInCompact = result.actionsToShowInCompact,
- semanticActions = result.semanticActions,
- packageName = sbn.packageName,
- token = result.token,
- clickIntent = result.clickIntent,
- device = result.device,
- active = active,
- resumeAction = resumeAction,
- playbackLocation = result.playbackLocation,
- notificationKey = key,
- hasCheckedForResume = hasCheckedForResume,
- isPlaying = result.isPlaying,
- isClearable = !sbn.isOngoing,
- lastActive = lastActive,
- createdTimestampMillis = createdTimestampMillis,
- instanceId = instanceId,
- appUid = result.appUid,
- isExplicit = result.isExplicit,
- )
- )
- }
+ withContext(mainDispatcher) { onMediaDataLoaded(key, oldKey, mediaData) }
}
@Deprecated("Cleanup when media_load_metadata_via_media_data_loader is cleaned up")
@@ -1001,13 +1009,13 @@
}
// Control buttons
- // If flag is enabled and controller has a PlaybackState, create actions from session info
+ // If controller has a PlaybackState, create actions from session info
// Otherwise, use the notification actions
- var actionIcons: List<MediaAction> = emptyList()
+ var actionIcons: List<MediaNotificationAction> = emptyList()
var actionsToShowCollapsed: List<Int> = emptyList()
val semanticActions = createActionsFromState(sbn.packageName, mediaController, sbn.user)
if (semanticActions == null) {
- val actions = createActionsFromNotification(context, activityStarter, sbn)
+ val actions = createActionsFromNotification(context, sbn)
actionIcons = actions.first
actionsToShowCollapsed = actions.second
}
@@ -1022,57 +1030,72 @@
else MediaData.PLAYBACK_CAST_LOCAL
val isPlaying = mediaController.playbackState?.let { isPlayingState(it.state) }
- val currentEntry = mediaDataRepository.mediaEntries.value.get(key)
- val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId()
+ val oldEntry = mediaDataRepository.mediaEntries.value.get(key)
+ val instanceId = oldEntry?.instanceId ?: logger.getNewInstanceId()
val appUid = appInfo?.uid ?: Process.INVALID_UID
+ val lastActive = systemClock.elapsedRealtime()
+ val createdTimestampMillis = oldEntry?.createdTimestampMillis ?: 0L
+ val resumeAction: Runnable? = mediaDataRepository.mediaEntries.value[key]?.resumeAction
+ val hasCheckedForResume =
+ mediaDataRepository.mediaEntries.value[key]?.hasCheckedForResume == true
+ val active = mediaDataRepository.mediaEntries.value[key]?.active ?: true
+ var mediaData =
+ MediaData(
+ sbn.normalizedUserId,
+ true,
+ appName,
+ smallIcon,
+ artist,
+ song,
+ artWorkIcon,
+ actionIcons,
+ actionsToShowCollapsed,
+ semanticActions,
+ sbn.packageName,
+ token,
+ notif.contentIntent,
+ device,
+ active,
+ resumeAction = resumeAction,
+ playbackLocation = playbackLocation,
+ notificationKey = key,
+ hasCheckedForResume = hasCheckedForResume,
+ isPlaying = isPlaying,
+ isClearable = !sbn.isOngoing,
+ lastActive = lastActive,
+ createdTimestampMillis = createdTimestampMillis,
+ instanceId = instanceId,
+ appUid = appUid,
+ isExplicit = isExplicit,
+ smartspaceId = SmallHash.hash(appUid + systemClock.currentTimeMillis().toInt()),
+ )
+
+ if (isSameMediaData(context, mediaController, mediaData, oldEntry)) {
+ mediaLogger.logDuplicateMediaNotification(key)
+ return
+ }
+
if (isNewlyActiveEntry) {
logSingleVsMultipleMediaAdded(appUid, sbn.packageName, instanceId)
logger.logActiveMediaAdded(appUid, sbn.packageName, instanceId, playbackLocation)
- } else if (playbackLocation != currentEntry?.playbackLocation) {
+ } else if (playbackLocation != oldEntry?.playbackLocation) {
logger.logPlaybackLocationChange(appUid, sbn.packageName, instanceId, playbackLocation)
}
- val lastActive = systemClock.elapsedRealtime()
- val createdTimestampMillis = currentEntry?.createdTimestampMillis ?: 0L
foregroundExecutor.execute {
- val resumeAction: Runnable? = mediaDataRepository.mediaEntries.value[key]?.resumeAction
- val hasCheckedForResume =
+ val oldResumeAction: Runnable? =
+ mediaDataRepository.mediaEntries.value[key]?.resumeAction
+ val oldHasCheckedForResume =
mediaDataRepository.mediaEntries.value[key]?.hasCheckedForResume == true
- val active = mediaDataRepository.mediaEntries.value[key]?.active ?: true
- onMediaDataLoaded(
- key,
- oldKey,
- MediaData(
- sbn.normalizedUserId,
- true,
- appName,
- smallIcon,
- artist,
- song,
- artWorkIcon,
- actionIcons,
- actionsToShowCollapsed,
- semanticActions,
- sbn.packageName,
- token,
- notif.contentIntent,
- device,
- active,
- resumeAction = resumeAction,
- playbackLocation = playbackLocation,
- notificationKey = key,
- hasCheckedForResume = hasCheckedForResume,
- isPlaying = isPlaying,
- isClearable = !sbn.isOngoing,
- lastActive = lastActive,
- createdTimestampMillis = createdTimestampMillis,
- instanceId = instanceId,
- appUid = appUid,
- isExplicit = isExplicit,
- smartspaceId = SmallHash.hash(appUid + systemClock.currentTimeMillis().toInt()),
+ val oldActive = mediaDataRepository.mediaEntries.value[key]?.active ?: true
+ mediaData =
+ mediaData.copy(
+ resumeAction = oldResumeAction,
+ hasCheckedForResume = oldHasCheckedForResume,
+ active = oldActive
)
- )
+ onMediaDataLoaded(key, oldKey, mediaData)
}
}
@@ -1402,7 +1425,7 @@
val updated =
data.copy(
token = null,
- actions = actions,
+ actions = listOf(),
semanticActions = MediaButton(playOrPause = resumeAction),
actionsToShowInCompact = listOf(0),
active = false,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceLogger.kt
deleted file mode 100644
index f886166..0000000
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceLogger.kt
+++ /dev/null
@@ -1,116 +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.systemui.media.controls.domain.pipeline
-
-import android.media.session.MediaController
-import com.android.settingslib.media.MediaDevice
-import com.android.systemui.log.LogBuffer
-import com.android.systemui.log.core.LogLevel
-import com.android.systemui.log.dagger.MediaDeviceLog
-import com.android.systemui.media.controls.shared.model.MediaDeviceData
-import javax.inject.Inject
-
-/** A [LogBuffer] for media device changes */
-class MediaDeviceLogger @Inject constructor(@MediaDeviceLog private val buffer: LogBuffer) {
-
- fun logBroadcastEvent(event: String, reason: Int, broadcastId: Int) {
- buffer.log(
- TAG,
- LogLevel.DEBUG,
- {
- str1 = event
- int1 = reason
- int2 = broadcastId
- },
- { "$str1, reason = $int1, broadcastId = $int2" }
- )
- }
-
- fun logBroadcastEvent(event: String, reason: Int) {
- buffer.log(
- TAG,
- LogLevel.DEBUG,
- {
- str1 = event
- int1 = reason
- },
- { "$str1, reason = $int1" }
- )
- }
-
- fun logBroadcastMetadataChanged(broadcastId: Int, metadata: String) {
- buffer.log(
- TAG,
- LogLevel.DEBUG,
- {
- int1 = broadcastId
- str1 = metadata
- },
- { "onBroadcastMetadataChanged, broadcastId = $int1, metadata = $str1" }
- )
- }
-
- fun logNewDeviceName(name: String?) {
- buffer.log(TAG, LogLevel.DEBUG, { str1 = name }, { "New device name $str1" })
- }
-
- fun logLocalDevice(sassDevice: MediaDeviceData?, connectedDevice: MediaDeviceData?) {
- buffer.log(
- TAG,
- LogLevel.DEBUG,
- {
- str1 = sassDevice?.name?.toString()
- str2 = connectedDevice?.name?.toString()
- },
- { "Local device: $str1 or $str2" }
- )
- }
-
- fun logRemoteDevice(routingSessionName: CharSequence?, connectedDevice: MediaDeviceData?) {
- buffer.log(
- TAG,
- LogLevel.DEBUG,
- {
- str1 = routingSessionName?.toString()
- str2 = connectedDevice?.name?.toString()
- },
- { "Remote device: $str1 or $str2 or unknown" }
- )
- }
-
- fun logDeviceName(
- device: MediaDevice?,
- controller: MediaController?,
- routingSessionName: CharSequence?,
- selectedRouteName: CharSequence?
- ) {
- buffer.log(
- TAG,
- LogLevel.DEBUG,
- {
- str1 = "device $device, controller: $controller"
- str2 = routingSessionName?.toString()
- str3 = selectedRouteName?.toString()
- },
- { "$str1, routingSession $str2 or selected route $str3" }
- )
- }
-
- companion object {
- private const val TAG = "MediaDeviceLog"
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManager.kt
index 49b53c2..a193f7f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManager.kt
@@ -71,7 +71,6 @@
private val localBluetoothManager: Lazy<LocalBluetoothManager?>,
@Main private val fgExecutor: Executor,
@Background private val bgExecutor: Executor,
- private val logger: MediaDeviceLogger,
) : MediaDataManager.Listener {
private val listeners: MutableSet<Listener> = mutableSetOf()
@@ -282,38 +281,59 @@
}
override fun onBroadcastStarted(reason: Int, broadcastId: Int) {
- logger.logBroadcastEvent("onBroadcastStarted", reason, broadcastId)
+ if (DEBUG) {
+ Log.d(TAG, "onBroadcastStarted(), reason = $reason , broadcastId = $broadcastId")
+ }
updateCurrent()
}
override fun onBroadcastStartFailed(reason: Int) {
- logger.logBroadcastEvent("onBroadcastStartFailed", reason)
+ if (DEBUG) {
+ Log.d(TAG, "onBroadcastStartFailed(), reason = $reason")
+ }
}
override fun onBroadcastMetadataChanged(
broadcastId: Int,
metadata: BluetoothLeBroadcastMetadata
) {
- logger.logBroadcastMetadataChanged(broadcastId, metadata.toString())
+ if (DEBUG) {
+ Log.d(
+ TAG,
+ "onBroadcastMetadataChanged(), broadcastId = $broadcastId , " +
+ "metadata = $metadata"
+ )
+ }
updateCurrent()
}
override fun onBroadcastStopped(reason: Int, broadcastId: Int) {
- logger.logBroadcastEvent("onBroadcastStopped", reason, broadcastId)
+ if (DEBUG) {
+ Log.d(TAG, "onBroadcastStopped(), reason = $reason , broadcastId = $broadcastId")
+ }
updateCurrent()
}
override fun onBroadcastStopFailed(reason: Int) {
- logger.logBroadcastEvent("onBroadcastStopFailed", reason)
+ if (DEBUG) {
+ Log.d(TAG, "onBroadcastStopFailed(), reason = $reason")
+ }
}
override fun onBroadcastUpdated(reason: Int, broadcastId: Int) {
- logger.logBroadcastEvent("onBroadcastUpdated", reason, broadcastId)
+ if (DEBUG) {
+ Log.d(TAG, "onBroadcastUpdated(), reason = $reason , broadcastId = $broadcastId")
+ }
updateCurrent()
}
override fun onBroadcastUpdateFailed(reason: Int, broadcastId: Int) {
- logger.logBroadcastEvent("onBroadcastUpdateFailed", reason, broadcastId)
+ if (DEBUG) {
+ Log.d(
+ TAG,
+ "onBroadcastUpdateFailed(), reason = $reason , " + "broadcastId = $broadcastId"
+ )
+ }
}
override fun onPlaybackStarted(reason: Int, broadcastId: Int) {}
@@ -361,16 +381,12 @@
name = context.getString(R.string.media_seamless_other_device),
showBroadcastButton = false
)
- logger.logRemoteDevice(routingSession?.name, connectedDevice)
} else {
// Prefer SASS if available when playback is local.
- val sassDevice = getSassDevice()
- activeDevice = sassDevice ?: connectedDevice
- logger.logLocalDevice(sassDevice, connectedDevice)
+ activeDevice = getSassDevice() ?: connectedDevice
}
current = activeDevice ?: EMPTY_AND_DISABLED_MEDIA_DEVICE_DATA
- logger.logNewDeviceName(current?.name?.toString())
} else {
val aboutToConnect = aboutToConnectDeviceOverride
if (
@@ -391,7 +407,9 @@
val enabled = device != null && (controller == null || routingSession != null)
val name = getDeviceName(device, routingSession)
- logger.logNewDeviceName(name)
+ if (DEBUG) {
+ Log.d(TAG, "new device name $name")
+ }
current =
MediaDeviceData(
enabled,
@@ -445,12 +463,14 @@
): String? {
val selectedRoutes = routingSession?.let { mr2manager.get().getSelectedRoutes(it) }
- logger.logDeviceName(
- device,
- controller,
- routingSession?.name,
- selectedRoutes?.firstOrNull()?.name
- )
+ if (DEBUG) {
+ Log.d(
+ TAG,
+ "device is $device, controller $controller," +
+ " routingSession ${routingSession?.name}" +
+ " or ${selectedRoutes?.firstOrNull()?.name}"
+ )
+ }
if (controller == null) {
// In resume state, we don't have a controller - just use the device name
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaProcessingHelper.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaProcessingHelper.kt
new file mode 100644
index 0000000..55d7b1d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaProcessingHelper.kt
@@ -0,0 +1,179 @@
+/*
+ * 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.media.controls.domain.pipeline
+
+import android.annotation.WorkerThread
+import android.app.PendingIntent
+import android.content.Context
+import android.graphics.drawable.Icon
+import android.media.session.MediaController
+import android.media.session.PlaybackState
+import android.util.Log
+import com.android.systemui.Flags.mediaControlsPostsOptimization
+import com.android.systemui.biometrics.Utils.toBitmap
+import com.android.systemui.media.controls.shared.model.MediaData
+
+private const val TAG = "MediaProcessingHelper"
+
+/**
+ * Compares [new] media data to [old] media data.
+ *
+ * @param context Context
+ * @param newController media controller of the new media data.
+ * @param new new media data.
+ * @param old old media data.
+ * @return whether new and old contain same data
+ */
+fun isSameMediaData(
+ context: Context,
+ newController: MediaController,
+ new: MediaData,
+ old: MediaData?
+): Boolean {
+ if (old == null || !mediaControlsPostsOptimization()) return false
+
+ return new.userId == old.userId &&
+ new.app == old.app &&
+ new.artist == old.artist &&
+ new.song == old.song &&
+ new.packageName == old.packageName &&
+ new.isExplicit == old.isExplicit &&
+ new.appUid == old.appUid &&
+ new.notificationKey == old.notificationKey &&
+ new.isPlaying == old.isPlaying &&
+ new.isClearable == old.isClearable &&
+ new.playbackLocation == old.playbackLocation &&
+ new.device == old.device &&
+ new.initialized == old.initialized &&
+ new.resumption == old.resumption &&
+ new.token == old.token &&
+ new.resumeProgress == old.resumeProgress &&
+ areClickIntentsEqual(new.clickIntent, old.clickIntent) &&
+ areActionsEqual(context, newController, new, old) &&
+ areIconsEqual(context, new.artwork, old.artwork) &&
+ areIconsEqual(context, new.appIcon, old.appIcon)
+}
+
+/** Returns whether actions lists are equal. */
+fun areCustomActionListsEqual(
+ first: List<PlaybackState.CustomAction>?,
+ second: List<PlaybackState.CustomAction>?
+): Boolean {
+ // Same object, or both null
+ if (first === second) {
+ return true
+ }
+
+ // Only one null, or different number of actions
+ if ((first == null || second == null) || (first.size != second.size)) {
+ return false
+ }
+
+ // Compare individual actions
+ first.asSequence().zip(second.asSequence()).forEach { (firstAction, secondAction) ->
+ if (!areCustomActionsEqual(firstAction, secondAction)) {
+ return false
+ }
+ }
+ return true
+}
+
+private fun areCustomActionsEqual(
+ firstAction: PlaybackState.CustomAction,
+ secondAction: PlaybackState.CustomAction
+): Boolean {
+ if (
+ firstAction.action != secondAction.action ||
+ firstAction.name != secondAction.name ||
+ firstAction.icon != secondAction.icon
+ ) {
+ return false
+ }
+
+ if ((firstAction.extras == null) != (secondAction.extras == null)) {
+ return false
+ }
+ if (firstAction.extras != null) {
+ firstAction.extras.keySet().forEach { key ->
+ if (firstAction.extras[key] != secondAction.extras[key]) {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+@WorkerThread
+private fun areIconsEqual(context: Context, new: Icon?, old: Icon?): Boolean {
+ if (new == old) return true
+ if (new == null || old == null || new.type != old.type) return false
+ return if (new.type == Icon.TYPE_BITMAP || new.type == Icon.TYPE_ADAPTIVE_BITMAP) {
+ if (new.bitmap.isRecycled || old.bitmap.isRecycled) {
+ Log.e(TAG, "Cannot compare recycled bitmap")
+ return false
+ }
+ new.bitmap.sameAs(old.bitmap)
+ } else {
+ val newDrawable = new.loadDrawable(context)
+ val oldDrawable = old.loadDrawable(context)
+
+ return newDrawable?.toBitmap()?.sameAs(oldDrawable?.toBitmap()) ?: false
+ }
+}
+
+private fun areActionsEqual(
+ context: Context,
+ newController: MediaController,
+ new: MediaData,
+ old: MediaData
+): Boolean {
+ val oldState = MediaController(context, old.token!!).playbackState
+ return if (
+ new.semanticActions == null &&
+ old.semanticActions == null &&
+ new.actions.size == old.actions.size
+ ) {
+ var same = true
+ new.actions.asSequence().zip(old.actions.asSequence()).forEach {
+ if (
+ it.first.actionIntent?.intent?.filterEquals(it.second.actionIntent?.intent) !=
+ true ||
+ it.first.icon != it.second.icon ||
+ it.first.contentDescription != it.second.contentDescription
+ ) {
+ same = false
+ return@forEach
+ }
+ }
+ same
+ } else if (new.semanticActions != null && old.semanticActions != null) {
+ oldState?.actions == newController.playbackState?.actions &&
+ areCustomActionListsEqual(
+ oldState?.customActions,
+ newController.playbackState?.customActions
+ )
+ } else {
+ false
+ }
+}
+
+private fun areClickIntentsEqual(newIntent: PendingIntent?, oldIntent: PendingIntent?): Boolean {
+ if ((newIntent == null && oldIntent == null) || newIntent === oldIntent) return true
+ if (newIntent == null || oldIntent == null) return false
+
+ return newIntent.intent?.filterEquals(oldIntent.intent) == true
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListener.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListener.kt
index fc31903..275f1ee 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListener.kt
@@ -16,12 +16,14 @@
package com.android.systemui.media.controls.domain.pipeline
+import android.annotation.WorkerThread
import android.media.session.MediaController
import android.media.session.MediaSession
import android.media.session.PlaybackState
import android.os.SystemProperties
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
@@ -32,6 +34,7 @@
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.time.SystemClock
+import java.util.concurrent.Executor
import java.util.concurrent.TimeUnit
import javax.inject.Inject
@@ -49,6 +52,8 @@
@Inject
constructor(
private val mediaControllerFactory: MediaControllerFactory,
+ @Background private val bgExecutor: Executor,
+ @Main private val uiExecutor: Executor,
@Main private val mainExecutor: DelayableExecutor,
private val logger: MediaTimeoutLogger,
statusBarStateController: SysuiStatusBarStateController,
@@ -147,19 +152,21 @@
}
reusedListener?.let {
- val wasPlaying = it.isPlaying()
- logger.logUpdateListener(key, wasPlaying)
- it.setMediaData(data)
- it.key = key
- mediaListeners[key] = it
- if (wasPlaying != it.isPlaying()) {
- // If a player becomes active because of a migration, we'll need to broadcast
- // its state. Doing it now would lead to reentrant callbacks, so let's wait
- // until we're done.
- mainExecutor.execute {
- if (mediaListeners[key]?.isPlaying() == true) {
- logger.logDelayedUpdate(key)
- timeoutCallback.invoke(key, false /* timedOut */)
+ bgExecutor.execute {
+ val wasPlaying = it.isPlaying()
+ logger.logUpdateListener(key, wasPlaying)
+ it.setMediaData(data)
+ it.key = key
+ mediaListeners[key] = it
+ if (wasPlaying != it.isPlaying()) {
+ // If a player becomes active because of a migration, we'll need to broadcast
+ // its state. Doing it now would lead to reentrant callbacks, so let's wait
+ // until we're done.
+ mainExecutor.execute {
+ if (mediaListeners[key]?.isPlaying() == true) {
+ logger.logDelayedUpdate(key)
+ timeoutCallback.invoke(key, false /* timedOut */)
+ }
}
}
}
@@ -217,18 +224,20 @@
private set
fun Int.isPlaying() = isPlayingState(this)
+
fun isPlaying() = lastState?.state?.isPlaying() ?: false
init {
- setMediaData(data)
+ bgExecutor.execute { setMediaData(data) }
}
fun destroy() {
- mediaController?.unregisterCallback(this)
+ bgExecutor.execute { mediaController?.unregisterCallback(this) }
cancellation?.run()
destroyed = true
}
+ @WorkerThread
fun setMediaData(data: MediaData) {
sessionToken = data.token
destroyed = false
@@ -258,7 +267,7 @@
if (resumption == true) {
// Some apps create a session when MBS is queried. We should unregister the
// controller since it will no longer be valid, but don't cancel the timeout
- mediaController?.unregisterCallback(this)
+ bgExecutor.execute { mediaController?.unregisterCallback(this) }
} else {
// For active controls, if the session is destroyed, clean up everything since we
// will need to recreate it if this key is updated later
@@ -284,7 +293,7 @@
if ((!actionsSame || !playingStateSame) && state != null && dispatchEvents) {
logger.logStateCallback(key)
- stateCallback.invoke(key, state)
+ uiExecutor.execute { stateCallback.invoke(key, state) }
}
if (playingStateSame && !resumptionChanged) {
@@ -313,7 +322,7 @@
expireMediaTimeout(key, "playback started - $state, $key")
timedOut = false
if (dispatchEvents) {
- timeoutCallback(key, timedOut)
+ uiExecutor.execute { timeoutCallback(key, timedOut) }
}
}
}
@@ -337,60 +346,13 @@
}
}
- private fun areCustomActionListsEqual(
- first: List<PlaybackState.CustomAction>?,
- second: List<PlaybackState.CustomAction>?
- ): Boolean {
- // Same object, or both null
- if (first === second) {
- return true
- }
-
- // Only one null, or different number of actions
- if ((first == null || second == null) || (first.size != second.size)) {
- return false
- }
-
- // Compare individual actions
- first.asSequence().zip(second.asSequence()).forEach { (firstAction, secondAction) ->
- if (!areCustomActionsEqual(firstAction, secondAction)) {
- return false
- }
- }
- return true
- }
-
- private fun areCustomActionsEqual(
- firstAction: PlaybackState.CustomAction,
- secondAction: PlaybackState.CustomAction
- ): Boolean {
- if (
- firstAction.action != secondAction.action ||
- firstAction.name != secondAction.name ||
- firstAction.icon != secondAction.icon
- ) {
- return false
- }
-
- if ((firstAction.extras == null) != (secondAction.extras == null)) {
- return false
- }
- if (firstAction.extras != null) {
- firstAction.extras.keySet().forEach { key ->
- if (firstAction.extras.get(key) != secondAction.extras.get(key)) {
- return false
- }
- }
- }
- return true
- }
-
/** Listens to changes in recommendation card data and schedules a timeout for its expiration */
private inner class RecommendationListener(var key: String, data: SmartspaceMediaData) {
private var timedOut = false
var destroyed = false
var expiration = Long.MAX_VALUE
private set
+
var cancellation: Runnable? = null
private set
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt
index 245f6f8..130868d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt
@@ -32,6 +32,7 @@
import com.android.systemui.bluetooth.BroadcastDialogController
import com.android.systemui.media.controls.data.repository.MediaFilterRepository
import com.android.systemui.media.controls.domain.pipeline.MediaDataProcessor
+import com.android.systemui.media.controls.domain.pipeline.getNotificationActions
import com.android.systemui.media.controls.shared.model.MediaControlModel
import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.media.controls.util.MediaSmartspaceLogger
@@ -102,7 +103,7 @@
artwork = artwork,
deviceData = device,
semanticActionButtons = semanticActions,
- notificationActionButtons = actions,
+ notificationActionButtons = getNotificationActions(data.actions, activityStarter),
actionsToShowInCollapsed = actionsToShowInCompact,
isDismissible = isClearable,
isResume = resumption,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/shared/MediaLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/shared/MediaLogger.kt
index 2b710b5..7d20e17 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/shared/MediaLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/shared/MediaLogger.kt
@@ -114,6 +114,15 @@
)
}
+ fun logDuplicateMediaNotification(key: String) {
+ buffer.log(
+ TAG,
+ LogLevel.DEBUG,
+ { str1 = key },
+ { "duplicate media notification $str1 posted" }
+ )
+ }
+
companion object {
private const val TAG = "MediaLog"
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaData.kt
index 40b3477..aed8609 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaData.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaData.kt
@@ -39,7 +39,7 @@
/** Album artwork. */
val artwork: Icon? = null,
/** List of generic action buttons for the media player, based on notification actions */
- val actions: List<MediaAction> = emptyList(),
+ val actions: List<MediaNotificationAction> = emptyList(),
/** Same as above, but shown on smaller versions of the player, like in QQS or keyguard. */
val actionsToShowInCompact: List<Int> = emptyList(),
/**
@@ -162,6 +162,14 @@
val rebindId: Int? = null
)
+/** State of a media action from notification. */
+data class MediaNotificationAction(
+ val isAuthenticationRequired: Boolean,
+ val actionIntent: PendingIntent?,
+ val icon: Drawable?,
+ val contentDescription: CharSequence?
+)
+
/** State of the media device. */
data class MediaDeviceData
@JvmOverloads
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 87610cf..8bec46a 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
@@ -21,6 +21,7 @@
import static com.android.settingslib.flags.Flags.legacyLeAudioSharing;
import static com.android.systemui.Flags.communalHub;
import static com.android.systemui.Flags.mediaLockscreenLaunchAnimation;
+import static com.android.systemui.media.controls.domain.pipeline.MediaActionsKt.getNotificationActions;
import static com.android.systemui.media.controls.shared.model.SmartspaceMediaDataKt.NUM_REQUIRED_RECOMMENDATIONS;
import android.animation.Animator;
@@ -1170,7 +1171,7 @@
// Set all the generic buttons
List<Integer> actionsWhenCollapsed = data.getActionsToShowInCompact();
- List<MediaAction> actions = data.getActions();
+ List<MediaAction> actions = getNotificationActions(data.getActions(), mActivityStarter);
int i = 0;
for (; i < actions.size() && i < genericButtons.size(); i++) {
boolean showInCompact = actionsWhenCollapsed.contains(i);
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
index a65243d..d4af1b5 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
@@ -29,9 +29,8 @@
* Check whether media control actions should be based on PlaybackState instead of notification
*/
fun areMediaSessionActionsEnabled(packageName: String, user: UserHandle): Boolean {
- val enabled = StatusBarManager.useMediaSessionActionsForApp(packageName, user)
// Allow global override with flag
- return enabled || featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS)
+ return StatusBarManager.useMediaSessionActionsForApp(packageName, user)
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 6bd880d..89d76f0 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -29,6 +29,7 @@
import static java.util.stream.Collectors.joining;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
@@ -1331,21 +1332,20 @@
}
}
- public void setBackAnimation(BackAnimation backAnimation) {
+ public void setBackAnimation(@Nullable BackAnimation backAnimation) {
mBackAnimation = backAnimation;
- mBackAnimation.setPilferPointerCallback(() -> {
- pilferPointers();
- });
- mBackAnimation.setTopUiRequestCallback(
- (requestTopUi, tag) -> mUiThreadContext.getExecutor().execute(() ->
- mNotificationShadeWindowController.setRequestTopUi(requestTopUi, tag)));
- updateBackAnimationThresholds();
- if (mLightBarControllerProvider.get() != null) {
- mBackAnimation.setStatusBarCustomizer((appearance) -> {
- mUiThreadContext.getExecutor().execute(() ->
- mLightBarControllerProvider.get()
- .customizeStatusBarAppearance(appearance));
- });
+ if (backAnimation != null) {
+ backAnimation.setPilferPointerCallback(this::pilferPointers);
+ backAnimation.setTopUiRequestCallback(
+ (requestTopUi, tag) -> mUiThreadContext.getExecutor().execute(() ->
+ mNotificationShadeWindowController.setRequestTopUi(requestTopUi, tag)));
+ updateBackAnimationThresholds();
+ if (mLightBarControllerProvider.get() != null) {
+ mBackAnimation.setStatusBarCustomizer((appearance) ->
+ mUiThreadContext.getExecutor().execute(() ->
+ mLightBarControllerProvider.get()
+ .customizeStatusBarAppearance(appearance)));
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModel.kt
index 6ef83e2..b6868c1 100644
--- a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModel.kt
@@ -21,13 +21,13 @@
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.scene.shared.model.Overlays
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
/** Models the UI state for the user actions for navigating to other scenes or overlays. */
class NotificationsShadeOverlayActionsViewModel @AssistedInject constructor() :
- SceneActionsViewModel() {
+ UserActionsViewModel() {
override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
setActions(
diff --git a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModel.kt
similarity index 68%
rename from packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneActionsViewModel.kt
rename to packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModel.kt
index 572a0ca..11854d9 100644
--- a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModel.kt
@@ -18,30 +18,36 @@
import com.android.compose.animation.scene.Back
import com.android.compose.animation.scene.Swipe
+import com.android.compose.animation.scene.SwipeDirection
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
+import com.android.compose.animation.scene.UserActionResult.ReplaceByOverlay
+import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.SceneFamilies
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
/**
* Models the UI state for the user actions that the user can perform to navigate to other scenes.
*/
-class NotificationsShadeSceneActionsViewModel @AssistedInject constructor() :
- SceneActionsViewModel() {
+class NotificationsShadeUserActionsViewModel @AssistedInject constructor() :
+ UserActionsViewModel() {
override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
setActions(
mapOf(
- Swipe.Up to SceneFamilies.Home,
Back to SceneFamilies.Home,
+ Swipe.Up to SceneFamilies.Home,
+ Swipe(direction = SwipeDirection.Down, fromSource = SceneContainerEdge.TopRight) to
+ ReplaceByOverlay(Overlays.QuickSettingsShade),
)
)
}
@AssistedFactory
interface Factory {
- fun create(): NotificationsShadeSceneActionsViewModel
+ fun create(): NotificationsShadeUserActionsViewModel
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index cbcf68c..2f843ac 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -50,10 +50,12 @@
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
+import com.android.systemui.Flags;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.util.concurrency.DelayableExecutor;
+import com.android.systemui.util.time.SystemClock;
import dagger.assisted.Assisted;
import dagger.assisted.AssistedFactory;
@@ -95,6 +97,7 @@
// Bind retry control.
private static final int MAX_BIND_RETRIES = 5;
private static final long DEFAULT_BIND_RETRY_DELAY = 5 * DateUtils.SECOND_IN_MILLIS;
+ private static final long ACTIVE_TILE_BIND_RETRY_DELAY = 1 * DateUtils.SECOND_IN_MILLIS;
private static final long LOW_MEMORY_BIND_RETRY_DELAY = 20 * DateUtils.SECOND_IN_MILLIS;
private static final long TILE_SERVICE_ONCLICK_ALLOW_LIST_DEFAULT_DURATION_MS = 15_000;
private static final String PROPERTY_TILE_SERVICE_ONCLICK_ALLOW_LIST_DURATION =
@@ -107,6 +110,7 @@
private final Intent mIntent;
private final UserHandle mUser;
private final DelayableExecutor mExecutor;
+ private final SystemClock mSystemClock;
private final IBinder mToken = new Binder();
private final PackageManagerAdapter mPackageManagerAdapter;
private final BroadcastDispatcher mBroadcastDispatcher;
@@ -120,7 +124,6 @@
private IBinder mClickBinder;
private int mBindTryCount;
- private long mBindRetryDelay = DEFAULT_BIND_RETRY_DELAY;
private AtomicBoolean isDeathRebindScheduled = new AtomicBoolean(false);
private AtomicBoolean mBound = new AtomicBoolean(false);
private AtomicBoolean mPackageReceiverRegistered = new AtomicBoolean(false);
@@ -138,7 +141,8 @@
TileLifecycleManager(@Main Handler handler, Context context, IQSService service,
PackageManagerAdapter packageManagerAdapter, BroadcastDispatcher broadcastDispatcher,
@Assisted Intent intent, @Assisted UserHandle user, ActivityManager activityManager,
- IDeviceIdleController deviceIdleController, @Background DelayableExecutor executor) {
+ IDeviceIdleController deviceIdleController, @Background DelayableExecutor executor,
+ SystemClock systemClock) {
mContext = context;
mHandler = handler;
mIntent = intent;
@@ -146,6 +150,7 @@
mIntent.putExtra(TileService.EXTRA_TOKEN, mToken);
mUser = user;
mExecutor = executor;
+ mSystemClock = systemClock;
mPackageManagerAdapter = packageManagerAdapter;
mBroadcastDispatcher = broadcastDispatcher;
mActivityManager = activityManager;
@@ -436,25 +441,31 @@
// If mBound is true (meaning that we should be bound), then reschedule binding for
// later.
if (mBound.get() && checkComponentState()) {
- if (isDeathRebindScheduled.compareAndSet(false, true)) {
+ if (isDeathRebindScheduled.compareAndSet(false, true)) { // if already not scheduled
+
+
mExecutor.executeDelayed(() -> {
// Only rebind if we are supposed to, but remove the scheduling anyway.
if (mBound.get()) {
setBindService(true);
}
- isDeathRebindScheduled.set(false);
+ isDeathRebindScheduled.set(false); // allow scheduling again
}, getRebindDelay());
}
}
});
}
+ private long mLastRebind = 0;
/**
* @return the delay to automatically rebind after a service died. It provides a longer delay if
* the device is a low memory state because the service is likely to get killed again by the
* system. In this case we want to rebind later and not to cause a loop of a frequent rebinds.
+ * It also provides a longer delay if called quickly (a few seconds) after a first call.
*/
private long getRebindDelay() {
+ final long now = mSystemClock.currentTimeMillis();
+
final ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
mActivityManager.getMemoryInfo(info);
@@ -462,7 +473,20 @@
if (info.lowMemory) {
delay = LOW_MEMORY_BIND_RETRY_DELAY;
} else {
- delay = mBindRetryDelay;
+ if (Flags.qsQuickRebindActiveTiles()) {
+ final long elapsedTimeSinceLastRebind = now - mLastRebind;
+ final boolean justAttemptedRebind =
+ elapsedTimeSinceLastRebind < DEFAULT_BIND_RETRY_DELAY;
+ if (isActiveTile() && !justAttemptedRebind) {
+ delay = ACTIVE_TILE_BIND_RETRY_DELAY;
+ } else {
+ delay = DEFAULT_BIND_RETRY_DELAY;
+ }
+ } else {
+ delay = DEFAULT_BIND_RETRY_DELAY;
+ }
+
+ mLastRebind = now;
}
if (mDebug) Log.i(TAG, "Rebinding with a delay=" + delay + " - " + getComponent());
return delay;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index d10471d..c5fa8cf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -44,7 +44,7 @@
/**
* Manages the priority which lets {@link TileServices} make decisions about which tiles
* to bind. Also holds on to and manages the {@link TileLifecycleManager}, informing it
- * of when it is allowed to bind based on decisions frome the {@link TileServices}.
+ * of when it is allowed to bind based on decisions from the {@link TileServices}.
*/
public class TileServiceManager {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java
index b96e83d..f723ff2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java
@@ -16,6 +16,8 @@
package com.android.systemui.qs.tiles;
+import static com.android.systemui.accessibility.hearingaid.HearingDevicesUiEventLogger.LAUNCH_SOURCE_QS_TILE;
+
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
@@ -96,7 +98,7 @@
@Override
protected void handleClick(@Nullable Expandable expandable) {
- mUiHandler.post(() -> mDialogManager.showDialog(expandable));
+ mUiHandler.post(() -> mDialogManager.showDialog(expandable, LAUNCH_SOURCE_QS_TILE));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt
index a3feb2b..d89e73d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt
@@ -43,12 +43,14 @@
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor
import com.android.systemui.qs.tileimpl.QSTileImpl
-import com.android.systemui.recordissue.IssueRecordingService
+import com.android.systemui.recordissue.IssueRecordingService.Companion.getStartIntent
+import com.android.systemui.recordissue.IssueRecordingService.Companion.getStopIntent
import com.android.systemui.recordissue.IssueRecordingState
import com.android.systemui.recordissue.RecordIssueDialogDelegate
import com.android.systemui.recordissue.RecordIssueModule.Companion.TILE_SPEC
import com.android.systemui.recordissue.TraceurMessageSender
import com.android.systemui.res.R
+import com.android.systemui.screenrecord.RecordingController
import com.android.systemui.screenrecord.RecordingService
import com.android.systemui.settings.UserContextProvider
import com.android.systemui.statusbar.phone.KeyguardDismissUtil
@@ -56,6 +58,9 @@
import java.util.concurrent.Executor
import javax.inject.Inject
+const val DELAY_MS: Long = 0
+const val INTERVAL_MS: Long = 1000
+
class RecordIssueTile
@Inject
constructor(
@@ -77,6 +82,7 @@
@Background private val bgExecutor: Executor,
private val issueRecordingState: IssueRecordingState,
private val delegateFactory: RecordIssueDialogDelegate.Factory,
+ private val recordingController: RecordingController,
) :
QSTileImpl<QSTile.BooleanState>(
host,
@@ -132,23 +138,25 @@
}
private fun startIssueRecordingService() =
- PendingIntent.getForegroundService(
- userContextProvider.userContext,
- RecordingService.REQUEST_CODE,
- IssueRecordingService.getStartIntent(userContextProvider.userContext),
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
- )
- .send(BroadcastOptions.makeBasic().apply { isInteractive = true }.toBundle())
+ recordingController.startCountdown(
+ DELAY_MS,
+ INTERVAL_MS,
+ pendingServiceIntent(getStartIntent(userContextProvider.userContext)),
+ pendingServiceIntent(getStopIntent(userContextProvider.userContext))
+ )
private fun stopIssueRecordingService() =
- PendingIntent.getService(
- userContextProvider.userContext,
- RecordingService.REQUEST_CODE,
- IssueRecordingService.getStopIntent(userContextProvider.userContext),
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
- )
+ pendingServiceIntent(getStopIntent(userContextProvider.userContext))
.send(BroadcastOptions.makeBasic().apply { isInteractive = true }.toBundle())
+ private fun pendingServiceIntent(action: Intent) =
+ PendingIntent.getService(
+ userContextProvider.userContext,
+ RecordingService.REQUEST_CODE,
+ action,
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
+ )
+
private fun showPrompt(expandable: Expandable?) {
val dialog: AlertDialog =
delegateFactory
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractor.kt
index 4971fef..0c8a375 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractor.kt
@@ -19,6 +19,7 @@
import android.app.AlertDialog
import android.app.BroadcastOptions
import android.app.PendingIntent
+import android.content.Intent
import android.util.Log
import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.animation.DialogCuj
@@ -27,12 +28,16 @@
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor
+import com.android.systemui.qs.tiles.DELAY_MS
+import com.android.systemui.qs.tiles.INTERVAL_MS
import com.android.systemui.qs.tiles.base.interactor.QSTileInput
import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
-import com.android.systemui.recordissue.IssueRecordingService
+import com.android.systemui.recordissue.IssueRecordingService.Companion.getStartIntent
+import com.android.systemui.recordissue.IssueRecordingService.Companion.getStopIntent
import com.android.systemui.recordissue.RecordIssueDialogDelegate
import com.android.systemui.recordissue.RecordIssueModule.Companion.TILE_SPEC
+import com.android.systemui.screenrecord.RecordingController
import com.android.systemui.screenrecord.RecordingService
import com.android.systemui.settings.UserContextProvider
import com.android.systemui.statusbar.phone.KeyguardDismissUtil
@@ -53,6 +58,7 @@
private val panelInteractor: PanelInteractor,
private val userContextProvider: UserContextProvider,
private val delegateFactory: RecordIssueDialogDelegate.Factory,
+ private val recordingController: RecordingController,
) : QSTileUserActionInteractor<IssueRecordingModel> {
override suspend fun handleInput(input: QSTileInput<IssueRecordingModel>) {
@@ -95,20 +101,22 @@
}
private fun startIssueRecordingService() =
- PendingIntent.getForegroundService(
- userContextProvider.userContext,
- RecordingService.REQUEST_CODE,
- IssueRecordingService.getStartIntent(userContextProvider.userContext),
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
- )
- .send(BroadcastOptions.makeBasic().apply { isInteractive = true }.toBundle())
+ recordingController.startCountdown(
+ DELAY_MS,
+ INTERVAL_MS,
+ pendingServiceIntent(getStartIntent(userContextProvider.userContext)),
+ pendingServiceIntent(getStopIntent(userContextProvider.userContext))
+ )
private fun stopIssueRecordingService() =
- PendingIntent.getService(
- userContextProvider.userContext,
- RecordingService.REQUEST_CODE,
- IssueRecordingService.getStopIntent(userContextProvider.userContext),
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
- )
+ pendingServiceIntent(getStopIntent(userContextProvider.userContext))
.send(BroadcastOptions.makeBasic().apply { isInteractive = true }.toBundle())
+
+ private fun pendingServiceIntent(action: Intent) =
+ PendingIntent.getService(
+ userContextProvider.userContext,
+ RecordingService.REQUEST_CODE,
+ action,
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
+ )
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt
index c2d112e..483373d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt
@@ -20,13 +20,16 @@
import android.content.Context
import android.os.UserHandle
import com.android.app.tracing.coroutines.flow.map
+import com.android.systemui.common.shared.model.Icon
import com.android.systemui.common.shared.model.asIcon
import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.qs.tiles.ModesTile
import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel
import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor
import com.android.systemui.statusbar.policy.domain.model.ActiveZenModes
+import com.android.systemui.statusbar.policy.domain.model.ZenModeInfo
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
@@ -61,28 +64,39 @@
suspend fun getCurrentTileModel() = buildTileData(zenModeInteractor.getActiveModes())
private fun buildTileData(activeModes: ActiveZenModes): ModesTileModel {
- val modesIconResId = com.android.internal.R.drawable.ic_zen_priority_modes
-
if (usesModeIcons()) {
- val mainModeDrawable = activeModes.mainMode?.icon?.drawable
- val iconResId = if (mainModeDrawable == null) modesIconResId else null
-
+ val tileIcon = getTileIcon(activeModes.mainMode)
return ModesTileModel(
isActivated = activeModes.isAnyActive(),
- icon = (mainModeDrawable ?: context.getDrawable(modesIconResId)!!).asIcon(),
- iconResId = iconResId,
+ icon = tileIcon.icon,
+ iconResId = tileIcon.resId,
activeModes = activeModes.modeNames
)
} else {
return ModesTileModel(
isActivated = activeModes.isAnyActive(),
- icon = context.getDrawable(modesIconResId)!!.asIcon(),
- iconResId = modesIconResId,
+ icon = context.getDrawable(ModesTile.ICON_RES_ID)!!.asIcon(),
+ iconResId = ModesTile.ICON_RES_ID,
activeModes = activeModes.modeNames
)
}
}
+ private data class TileIcon(val icon: Icon.Loaded, val resId: Int?)
+
+ private fun getTileIcon(activeMode: ZenModeInfo?): TileIcon {
+ return if (activeMode != null) {
+ // ZenIconKey.resPackage is null if its resId is a system icon.
+ if (activeMode.icon.key.resPackage == null) {
+ TileIcon(activeMode.icon.drawable.asIcon(), activeMode.icon.key.resId)
+ } else {
+ TileIcon(activeMode.icon.drawable.asIcon(), null)
+ }
+ } else {
+ TileIcon(context.getDrawable(ModesTile.ICON_RES_ID)!!.asIcon(), ModesTile.ICON_RES_ID)
+ }
+ }
+
override fun availability(user: UserHandle): Flow<Boolean> = flowOf(Flags.modesUi())
private fun usesModeIcons() = Flags.modesApi() && Flags.modesUi() && Flags.modesUiIcons()
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt
index 7f571b1..69da313 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt
@@ -36,9 +36,7 @@
) : QSTileDataToStateMapper<ModesTileModel> {
override fun map(config: QSTileConfig, data: ModesTileModel): QSTileState =
QSTileState.build(resources, theme, config.uiConfig) {
- if (!android.app.Flags.modesUiIcons()) {
- iconRes = data.iconResId
- }
+ iconRes = data.iconResId
icon = { data.icon }
activationState =
if (data.isActivated) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModel.kt
index a264f51..f77386d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModel.kt
@@ -39,7 +39,7 @@
/**
* Models UI state needed for rendering the content of the quick settings scene.
*
- * Different from [QuickSettingsSceneActionsViewModel] that models the UI state needed to figure out
+ * Different from [QuickSettingsUserActionsViewModel] that models the UI state needed to figure out
* which user actions can trigger navigation to other scenes.
*/
class QuickSettingsSceneContentViewModel
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModel.kt
index 9538392..61c4c8c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModel.kt
@@ -21,13 +21,13 @@
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.scene.shared.model.Overlays
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
/** Models the UI state for the user actions for navigating to other scenes or overlays. */
class QuickSettingsShadeOverlayActionsViewModel @AssistedInject constructor() :
- SceneActionsViewModel() {
+ UserActionsViewModel() {
override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
setActions(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneContentViewModel.kt
index 5185828..d01b33b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneContentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneContentViewModel.kt
@@ -22,7 +22,7 @@
/**
* Models UI state used to render the content of the quick settings shade scene.
*
- * Different from [QuickSettingsShadeSceneActionsViewModel], which only models user actions that can
+ * Different from [QuickSettingsShadeUserActionsViewModel], which only models user actions that can
* be performed to navigate to other scenes.
*/
class QuickSettingsShadeSceneContentViewModel
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModel.kt
similarity index 71%
rename from packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModel.kt
rename to packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModel.kt
index 9690aab..bd1872d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModel.kt
@@ -18,10 +18,14 @@
import com.android.compose.animation.scene.Back
import com.android.compose.animation.scene.Swipe
+import com.android.compose.animation.scene.SwipeDirection
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
+import com.android.compose.animation.scene.UserActionResult.ReplaceByOverlay
+import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.SceneFamilies
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.map
@@ -32,17 +36,24 @@
* Different from the [QuickSettingsShadeSceneContentViewModel] which models the _content_ of the
* scene.
*/
-class QuickSettingsShadeSceneActionsViewModel
+class QuickSettingsShadeUserActionsViewModel
@AssistedInject
constructor(
val quickSettingsContainerViewModel: QuickSettingsContainerViewModel,
-) : SceneActionsViewModel() {
+) : UserActionsViewModel() {
override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
quickSettingsContainerViewModel.editModeViewModel.isEditing
.map { editing ->
buildMap {
put(Swipe.Up, UserActionResult(SceneFamilies.Home))
+ put(
+ Swipe(
+ direction = SwipeDirection.Down,
+ fromSource = SceneContainerEdge.TopLeft
+ ),
+ ReplaceByOverlay(Overlays.NotificationsShade)
+ )
if (!editing) {
put(Back, UserActionResult(SceneFamilies.Home))
}
@@ -53,6 +64,6 @@
@AssistedFactory
interface Factory {
- fun create(): QuickSettingsShadeSceneActionsViewModel
+ fun create(): QuickSettingsShadeUserActionsViewModel
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModel.kt
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModel.kt
rename to packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModel.kt
index 2bb5dc66..54e5cac 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModel.kt
@@ -27,7 +27,7 @@
import com.android.systemui.scene.domain.interactor.SceneBackInteractor
import com.android.systemui.scene.shared.model.SceneFamilies
import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.Flow
@@ -42,12 +42,12 @@
* Different from [QuickSettingsSceneContentViewModel] that models UI state needed for rendering the
* content of the quick settings scene.
*/
-class QuickSettingsSceneActionsViewModel
+class QuickSettingsUserActionsViewModel
@AssistedInject
constructor(
private val qsSceneAdapter: QSSceneAdapter,
sceneBackInteractor: SceneBackInteractor,
-) : SceneActionsViewModel() {
+) : UserActionsViewModel() {
private val backScene: Flow<SceneKey> =
sceneBackInteractor.backScene
@@ -82,6 +82,6 @@
@AssistedFactory
interface Factory {
- fun create(): QuickSettingsSceneActionsViewModel
+ fun create(): QuickSettingsUserActionsViewModel
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt
index 3d6d00e..a5f4a89 100644
--- a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt
+++ b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt
@@ -23,8 +23,6 @@
import android.content.res.Resources
import android.net.Uri
import android.os.Handler
-import android.os.UserHandle
-import android.provider.Settings
import android.util.Log
import com.android.internal.logging.UiEventLogger
import com.android.systemui.animation.DialogTransitionAnimator
@@ -50,11 +48,11 @@
notificationManager: NotificationManager,
userContextProvider: UserContextProvider,
keyguardDismissUtil: KeyguardDismissUtil,
- private val dialogTransitionAnimator: DialogTransitionAnimator,
- private val panelInteractor: PanelInteractor,
- private val traceurMessageSender: TraceurMessageSender,
+ dialogTransitionAnimator: DialogTransitionAnimator,
+ panelInteractor: PanelInteractor,
+ traceurMessageSender: TraceurMessageSender,
private val issueRecordingState: IssueRecordingState,
- private val iActivityManager: IActivityManager,
+ iActivityManager: IActivityManager,
) :
RecordingService(
controller,
@@ -66,6 +64,18 @@
keyguardDismissUtil
) {
+ private val commandHandler =
+ IssueRecordingServiceCommandHandler(
+ bgExecutor,
+ dialogTransitionAnimator,
+ panelInteractor,
+ traceurMessageSender,
+ issueRecordingState,
+ iActivityManager,
+ notificationManager,
+ userContextProvider,
+ )
+
override fun getTag(): String = TAG
override fun getChannelId(): String = CHANNEL_ID
@@ -76,10 +86,7 @@
Log.d(getTag(), "handling action: ${intent?.action}")
when (intent?.action) {
ACTION_START -> {
- bgExecutor.execute {
- traceurMessageSender.startTracing(issueRecordingState.traceConfig)
- }
- issueRecordingState.isRecording = true
+ commandHandler.handleStartCommand()
if (!issueRecordingState.recordScreen) {
// If we don't want to record the screen, the ACTION_SHOW_START_NOTIF action
// will circumvent the RecordingService's screen recording start code.
@@ -87,41 +94,13 @@
}
}
ACTION_STOP,
- ACTION_STOP_NOTIF -> {
- // ViewCapture needs to save it's data before it is disabled, or else the data will
- // be lost. This is expected to change in the near future, and when that happens
- // this line should be removed.
- bgExecutor.execute {
- if (issueRecordingState.traceConfig.longTrace) {
- Settings.Global.putInt(
- contentResolver,
- NOTIFY_SESSION_ENDED_SETTING,
- DISABLED
- )
- }
- traceurMessageSender.stopTracing()
- }
- issueRecordingState.isRecording = false
- }
+ ACTION_STOP_NOTIF -> commandHandler.handleStopCommand(contentResolver)
ACTION_SHARE -> {
- bgExecutor.execute {
- mNotificationManager.cancelAsUser(
- null,
- intent.getIntExtra(EXTRA_NOTIFICATION_ID, mNotificationId),
- UserHandle(mUserContextTracker.userContext.userId)
- )
-
- val screenRecording = intent.getParcelableExtra(EXTRA_PATH, Uri::class.java)
- if (issueRecordingState.takeBugreport) {
- iActivityManager.requestBugReportWithExtraAttachment(screenRecording)
- } else {
- traceurMessageSender.shareTraces(applicationContext, screenRecording)
- }
- }
-
- dialogTransitionAnimator.disableAllCurrentDialogsExitAnimations()
- panelInteractor.collapsePanels()
-
+ commandHandler.handleShareCommand(
+ intent.getIntExtra(EXTRA_NOTIFICATION_ID, mNotificationId),
+ intent.getParcelableExtra(EXTRA_PATH, Uri::class.java),
+ this
+ )
// Unlike all other actions, action_share has different behavior for the screen
// recording qs tile than it does for the record issue qs tile. Return sticky to
// avoid running any of the base class' code for this action.
@@ -135,8 +114,6 @@
companion object {
private const val TAG = "IssueRecordingService"
private const val CHANNEL_ID = "issue_record"
- private const val NOTIFY_SESSION_ENDED_SETTING = "should_notify_trace_session_ended"
- private const val DISABLED = 0
/**
* Get an intent to stop the issue recording service.
diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceCommandHandler.kt b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceCommandHandler.kt
new file mode 100644
index 0000000..32de0f3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceCommandHandler.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.recordissue
+
+import android.app.IActivityManager
+import android.app.NotificationManager
+import android.content.ContentResolver
+import android.content.Context
+import android.net.Uri
+import android.os.UserHandle
+import android.provider.Settings
+import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor
+import com.android.systemui.settings.UserContextProvider
+import java.util.concurrent.Executor
+
+private const val NOTIFY_SESSION_ENDED_SETTING = "should_notify_trace_session_ended"
+private const val DISABLED = 0
+
+/**
+ * This class exists to unit test the business logic encapsulated in IssueRecordingService. Android
+ * specifically calls out that there is no supported way to test IntentServices here:
+ * https://developer.android.com/training/testing/other-components/services
+ */
+class IssueRecordingServiceCommandHandler(
+ private val bgExecutor: Executor,
+ private val dialogTransitionAnimator: DialogTransitionAnimator,
+ private val panelInteractor: PanelInteractor,
+ private val traceurMessageSender: TraceurMessageSender,
+ private val issueRecordingState: IssueRecordingState,
+ private val iActivityManager: IActivityManager,
+ private val notificationManager: NotificationManager,
+ private val userContextProvider: UserContextProvider,
+) {
+
+ fun handleStartCommand() {
+ bgExecutor.execute { traceurMessageSender.startTracing(issueRecordingState.traceConfig) }
+ issueRecordingState.isRecording = true
+ }
+
+ fun handleStopCommand(contentResolver: ContentResolver) {
+ bgExecutor.execute {
+ if (issueRecordingState.traceConfig.longTrace) {
+ Settings.Global.putInt(contentResolver, NOTIFY_SESSION_ENDED_SETTING, DISABLED)
+ }
+ traceurMessageSender.stopTracing()
+ }
+ issueRecordingState.isRecording = false
+ }
+
+ fun handleShareCommand(notificationId: Int, screenRecording: Uri?, context: Context) {
+ bgExecutor.execute {
+ notificationManager.cancelAsUser(
+ null,
+ notificationId,
+ UserHandle(userContextProvider.userContext.userId)
+ )
+
+ if (issueRecordingState.takeBugreport) {
+ iActivityManager.requestBugReportWithExtraAttachment(screenRecording)
+ } else {
+ traceurMessageSender.shareTraces(context, screenRecording)
+ }
+ }
+
+ dialogTransitionAnimator.disableAllCurrentDialogsExitAnimations()
+ panelInteractor.collapsePanels()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
index 00944b8..834db98 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
@@ -16,6 +16,7 @@
package com.android.systemui.scene
+import androidx.compose.ui.unit.dp
import com.android.systemui.CoreStartable
import com.android.systemui.notifications.ui.composable.NotificationsShadeSessionModule
import com.android.systemui.scene.domain.SceneDomainModule
@@ -30,6 +31,8 @@
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.scene.ui.viewmodel.SplitEdgeDetector
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.shared.flag.DualShade
import dagger.Binds
import dagger.Module
@@ -119,5 +122,15 @@
.mapValues { checkNotNull(it.value) }
)
}
+
+ @Provides
+ fun splitEdgeDetector(shadeInteractor: ShadeInteractor): SplitEdgeDetector {
+ return SplitEdgeDetector(
+ topEdgeSplitFraction = shadeInteractor::getTopEdgeSplitFraction,
+ // TODO(b/338577208): This should be 60dp at the top in the dual-shade UI. Better to
+ // replace this constant with dynamic window insets.
+ edgeSize = 40.dp
+ )
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
index 4061ad8..a4c7d00 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
@@ -16,6 +16,7 @@
package com.android.systemui.scene
+import androidx.compose.ui.unit.dp
import com.android.systemui.CoreStartable
import com.android.systemui.notifications.ui.composable.NotificationsShadeSessionModule
import com.android.systemui.scene.domain.SceneDomainModule
@@ -30,6 +31,8 @@
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.scene.ui.viewmodel.SplitEdgeDetector
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.shared.flag.DualShade
import dagger.Binds
import dagger.Module
@@ -129,5 +132,15 @@
.mapValues { checkNotNull(it.value) }
)
}
+
+ @Provides
+ fun splitEdgeDetector(shadeInteractor: ShadeInteractor): SplitEdgeDetector {
+ return SplitEdgeDetector(
+ topEdgeSplitFraction = shadeInteractor::getTopEdgeSplitFraction,
+ // TODO(b/338577208): This should be 60dp at the top in the dual-shade UI. Better to
+ // replace this constant with dynamic window insets.
+ edgeSize = 40.dp
+ )
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt
index e51a8bc..738b184 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt
@@ -38,6 +38,8 @@
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapConcat
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
@@ -73,22 +75,34 @@
sceneInteractorProvider
.get()
.transitionState
- .map { state ->
+ .flatMapConcat { state ->
when (state) {
is ObservableTransitionState.Idle ->
- state.currentScene == Scenes.Shade ||
- state.currentScene == Scenes.NotificationsShade ||
- state.currentScene == Scenes.QuickSettingsShade ||
- state.currentScene == Scenes.Lockscreen
+ flowOf(
+ state.currentScene == Scenes.Shade ||
+ state.currentScene == Scenes.NotificationsShade ||
+ state.currentScene == Scenes.QuickSettingsShade ||
+ state.currentScene == Scenes.Lockscreen
+ )
is ObservableTransitionState.Transition ->
- state.toContent == Scenes.Shade ||
- state.toContent == Scenes.NotificationsShade ||
- state.toContent == Scenes.QuickSettingsShade ||
- state.toContent == Scenes.Lockscreen ||
- state.fromContent == Scenes.Shade ||
- state.fromContent == Scenes.NotificationsShade ||
- state.fromContent == Scenes.QuickSettingsShade ||
- state.fromContent == Scenes.Lockscreen
+ if (
+ state.fromContent == Scenes.Bouncer &&
+ state.toContent == Scenes.Lockscreen
+ ) {
+ // Lockscreen is not visible during preview stage of predictive back
+ state.isInPreviewStage.map { !it }
+ } else {
+ flowOf(
+ state.toContent == Scenes.Shade ||
+ state.toContent == Scenes.NotificationsShade ||
+ state.toContent == Scenes.QuickSettingsShade ||
+ state.toContent == Scenes.Lockscreen ||
+ state.fromContent == Scenes.Shade ||
+ state.fromContent == Scenes.NotificationsShade ||
+ state.fromContent == Scenes.QuickSettingsShade ||
+ state.fromContent == Scenes.Lockscreen
+ )
+ }
}
}
.distinctUntilChanged()
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 0a7526a..98907b0 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
@@ -22,7 +22,9 @@
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
import com.android.internal.logging.UiEventLogger
+import com.android.keyguard.AuthInteractionProperties
import com.android.systemui.CoreStartable
+import com.android.systemui.Flags
import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
@@ -36,6 +38,7 @@
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.DisplayId
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.deviceentry.domain.interactor.DeviceUnlockedInteractor
import com.android.systemui.deviceentry.shared.model.DeviceUnlockSource
@@ -62,6 +65,7 @@
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationInteractor
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor
@@ -71,6 +75,8 @@
import com.android.systemui.util.kotlin.sample
import com.android.systemui.util.printSection
import com.android.systemui.util.println
+import com.google.android.msdl.data.model.MSDLToken
+import com.google.android.msdl.domain.MSDLPlayer
import dagger.Lazy
import java.io.PrintWriter
import java.util.Optional
@@ -78,6 +84,7 @@
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
@@ -107,6 +114,7 @@
@Application private val applicationScope: CoroutineScope,
private val sceneInteractor: SceneInteractor,
private val deviceEntryInteractor: DeviceEntryInteractor,
+ private val deviceEntryHapticsInteractor: DeviceEntryHapticsInteractor,
private val deviceUnlockedInteractor: DeviceUnlockedInteractor,
private val bouncerInteractor: BouncerInteractor,
private val keyguardInteractor: KeyguardInteractor,
@@ -134,10 +142,14 @@
private val dismissCallbackRegistry: DismissCallbackRegistry,
private val statusBarStateController: SysuiStatusBarStateController,
private val alternateBouncerInteractor: AlternateBouncerInteractor,
+ private val vibratorHelper: VibratorHelper,
+ private val msdlPlayer: MSDLPlayer,
) : CoreStartable {
private val centralSurfaces: CentralSurfaces?
get() = centralSurfacesOptLazy.get().getOrNull()
+ private val authInteractionProperties = AuthInteractionProperties()
+
override fun start() {
if (SceneContainerFlag.isEnabled) {
sceneLogger.logFrameworkEnabled(isEnabled = true)
@@ -148,6 +160,7 @@
respondToFalsingDetections()
hydrateInteractionState()
handleBouncerOverscroll()
+ handleDeviceEntryHapticsWhileDeviceLocked()
hydrateWindowController()
hydrateBackStack()
resetShadeSessions()
@@ -525,6 +538,51 @@
}
}
+ private fun handleDeviceEntryHapticsWhileDeviceLocked() {
+ applicationScope.launch {
+ deviceEntryInteractor.isDeviceEntered.collectLatest { isDeviceEntered ->
+ // Only check for haptics signals before device is entered
+ if (!isDeviceEntered) {
+ coroutineScope {
+ launch {
+ deviceEntryHapticsInteractor.playSuccessHaptic
+ .sample(sceneInteractor.currentScene)
+ .collect { currentScene ->
+ if (Flags.msdlFeedback()) {
+ msdlPlayer.playToken(
+ MSDLToken.UNLOCK,
+ authInteractionProperties,
+ )
+ } else {
+ vibratorHelper.vibrateAuthSuccess(
+ "$TAG, $currentScene device-entry::success"
+ )
+ }
+ }
+ }
+
+ launch {
+ deviceEntryHapticsInteractor.playErrorHaptic
+ .sample(sceneInteractor.currentScene)
+ .collect { currentScene ->
+ if (Flags.msdlFeedback()) {
+ msdlPlayer.playToken(
+ MSDLToken.FAILURE,
+ authInteractionProperties,
+ )
+ } else {
+ vibratorHelper.vibrateAuthError(
+ "$TAG, $currentScene device-entry::error"
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
/** Keeps [SysUiState] up-to-date */
private fun hydrateSystemUiState() {
applicationScope.launch {
@@ -571,15 +629,6 @@
}
applicationScope.launch {
- sceneInteractor.currentScene
- .map { it == Scenes.Bouncer }
- .distinctUntilChanged()
- .collect { isBouncerShowing ->
- windowController.setBouncerShowing(isBouncerShowing)
- }
- }
-
- applicationScope.launch {
occlusionInteractor.invisibleDueToOcclusion.collect { invisibleDueToOcclusion ->
windowController.setKeyguardOccluded(invisibleDueToOcclusion)
}
@@ -817,4 +866,8 @@
.collectLatest { deviceEntryInteractor.refreshLockscreenEnabled() }
}
}
+
+ companion object {
+ private const val TAG = "SceneContainerStartable"
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt
index fcf6288..115d664 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt
@@ -72,9 +72,7 @@
* and one for quick settings, [NotificationsShade] and [QuickSettingsShade] scenes are used
* respectively.
*/
- @Deprecated("The quick settings shade scene has been replaced by an overlay")
- @JvmField
- val QuickSettings = SceneKey("quick_settings")
+ @JvmField val QuickSettings = SceneKey("quick_settings")
/**
* The quick settings shade scene shows the quick setting tiles as an overlay UI.
@@ -87,7 +85,9 @@
* large screens or unfolded foldables, where notifications and quick settings are shown
* side-by-side in their own columns).
*/
- @JvmField val QuickSettingsShade = SceneKey("quick_settings_shade")
+ @Deprecated("The quick settings shade scene has been replaced by an overlay")
+ @JvmField
+ val QuickSettingsShade = SceneKey("quick_settings_shade")
/**
* The shade is the scene that shows a scrollable list of notifications and the minimized
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
index 075599b..7f35d73 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
@@ -77,29 +77,31 @@
alternateBouncerDependencies: AlternateBouncerDependencies,
) {
val unsortedSceneByKey: Map<SceneKey, Scene> = scenes.associateBy { scene -> scene.key }
- val sortedSceneByKey: Map<SceneKey, Scene> = buildMap {
- containerConfig.sceneKeys.forEach { sceneKey ->
- val scene =
- checkNotNull(unsortedSceneByKey[sceneKey]) {
- "Scene not found for key \"$sceneKey\"!"
- }
+ val sortedSceneByKey: Map<SceneKey, Scene> =
+ LinkedHashMap<SceneKey, Scene>(containerConfig.sceneKeys.size).apply {
+ containerConfig.sceneKeys.forEach { sceneKey ->
+ val scene =
+ checkNotNull(unsortedSceneByKey[sceneKey]) {
+ "Scene not found for key \"$sceneKey\"!"
+ }
- put(sceneKey, scene)
+ put(sceneKey, scene)
+ }
}
- }
val unsortedOverlayByKey: Map<OverlayKey, Overlay> =
overlays.associateBy { overlay -> overlay.key }
- val sortedOverlayByKey: Map<OverlayKey, Overlay> = buildMap {
- containerConfig.overlayKeys.forEach { overlayKey ->
- val overlay =
- checkNotNull(unsortedOverlayByKey[overlayKey]) {
- "Overlay not found for key \"$overlayKey\"!"
- }
+ val sortedOverlayByKey: Map<OverlayKey, Overlay> =
+ LinkedHashMap<OverlayKey, Overlay>(containerConfig.overlayKeys.size).apply {
+ containerConfig.overlayKeys.forEach { overlayKey ->
+ val overlay =
+ checkNotNull(unsortedOverlayByKey[overlayKey]) {
+ "Overlay not found for key \"$overlayKey\"!"
+ }
- put(overlayKey, overlay)
+ put(overlayKey, overlay)
+ }
}
- }
view.repeatWhenAttached {
view.viewModel(
@@ -148,7 +150,7 @@
)
view.addView(sharedNotificationContainer)
- // TODO (b/358354906): use an overlay for the alternate bouncer
+ // TODO(b/358354906): use an overlay for the alternate bouncer
view.addView(
createAlternateBouncerView(
context = view.context,
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModel.kt
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneActionsViewModel.kt
rename to packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModel.kt
index 7b0e7f4..ea4122a 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModel.kt
@@ -29,11 +29,11 @@
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.map
-class GoneSceneActionsViewModel
+class GoneUserActionsViewModel
@AssistedInject
constructor(
private val shadeInteractor: ShadeInteractor,
-) : SceneActionsViewModel() {
+) : UserActionsViewModel() {
override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
shadeInteractor.shadeMode
@@ -69,6 +69,6 @@
@AssistedFactory
interface Factory {
- fun create(): GoneSceneActionsViewModel
+ fun create(): GoneUserActionsViewModel
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
index a73c39d..5482394 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
@@ -18,8 +18,12 @@
import android.view.MotionEvent
import androidx.compose.runtime.getValue
+import com.android.compose.animation.scene.ContentKey
+import com.android.compose.animation.scene.DefaultEdgeDetector
import com.android.compose.animation.scene.ObservableTransitionState
+import com.android.compose.animation.scene.OverlayKey
import com.android.compose.animation.scene.SceneKey
+import com.android.compose.animation.scene.SwipeSourceDetector
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.classifier.Classifier
@@ -30,12 +34,16 @@
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.logger.SceneLogger
import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.scene.ui.composable.Overlay
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.map
/** Models UI state for the scene container. */
class SceneContainerViewModel
@@ -44,6 +52,8 @@
private val sceneInteractor: SceneInteractor,
private val falsingInteractor: FalsingInteractor,
private val powerInteractor: PowerInteractor,
+ private val shadeInteractor: ShadeInteractor,
+ private val splitEdgeDetector: SplitEdgeDetector,
private val logger: SceneLogger,
@Assisted private val motionEventHandlerReceiver: (MotionEventHandler?) -> Unit,
) : ExclusiveActivatable() {
@@ -56,6 +66,20 @@
/** Whether the container is visible. */
val isVisible: Boolean by hydrator.hydratedStateOf("isVisible", sceneInteractor.isVisible)
+ /**
+ * The [SwipeSourceDetector] to use for defining which edges of the screen can be defined in the
+ * [UserAction]s for this container.
+ */
+ val edgeDetector: SwipeSourceDetector by
+ hydrator.hydratedStateOf(
+ traceName = "edgeDetector",
+ initialValue = DefaultEdgeDetector,
+ source =
+ shadeInteractor.shadeMode.map {
+ if (it is ShadeMode.Dual) splitEdgeDetector else DefaultEdgeDetector
+ }
+ )
+
override suspend fun onActivated(): Nothing {
try {
// Sends a MotionEventHandler to the owner of the view-model so they can report
@@ -83,7 +107,7 @@
/**
* Binds the given flow so the system remembers it.
*
- * Note that you must call is with `null` when the UI is done or risk a memory leak.
+ * Note that you must call this with `null` when the UI is done or risk a memory leak.
*/
fun setTransitionState(transitionState: Flow<ObservableTransitionState>?) {
sceneInteractor.setTransitionState(transitionState)
@@ -197,6 +221,29 @@
}
}
+ /**
+ * Returns the [ContentKey] whose user actions should be active.
+ *
+ * @param overlayByKey Mapping of [Overlay] by [OverlayKey], ordered by z-order such that the
+ * last overlay is rendered on top of all other overlays.
+ */
+ fun getActionableContentKey(
+ currentScene: SceneKey,
+ currentOverlays: Set<OverlayKey>,
+ overlayByKey: Map<OverlayKey, Overlay>,
+ ): ContentKey {
+ // Overlay actions take precedence over scene actions.
+ return when (currentOverlays.size) {
+ // No overlays, the scene is actionable.
+ 0 -> currentScene
+ // Small optimization for the most common case.
+ 1 -> currentOverlays.first()
+ // Find the top-most overlay by z-index.
+ else ->
+ checkNotNull(overlayByKey.asSequence().findLast { it.key in currentOverlays }?.key)
+ }
+ }
+
/** Defines interface for classes that can handle externally-reported [MotionEvent]s. */
interface MotionEventHandler {
/** Notifies that a [MotionEvent] has occurred. */
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetector.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetector.kt
new file mode 100644
index 0000000..f88bcb5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetector.kt
@@ -0,0 +1,116 @@
+/*
+ * 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.scene.ui.viewmodel
+
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.LayoutDirection
+import com.android.compose.animation.scene.Edge
+import com.android.compose.animation.scene.FixedSizeEdgeDetector
+import com.android.compose.animation.scene.SwipeSource
+import com.android.compose.animation.scene.SwipeSourceDetector
+
+/**
+ * The edge of a [SceneContainer]. It differs from a standard [Edge] by splitting the top edge into
+ * top-left and top-right.
+ */
+enum class SceneContainerEdge(private val resolveEdge: (LayoutDirection) -> Resolved) :
+ SwipeSource {
+ TopLeft(resolveEdge = { Resolved.TopLeft }),
+ TopRight(resolveEdge = { Resolved.TopRight }),
+ TopStart(
+ resolveEdge = { if (it == LayoutDirection.Ltr) Resolved.TopLeft else Resolved.TopRight }
+ ),
+ TopEnd(
+ resolveEdge = { if (it == LayoutDirection.Ltr) Resolved.TopRight else Resolved.TopLeft }
+ ),
+ Bottom(resolveEdge = { Resolved.Bottom }),
+ Left(resolveEdge = { Resolved.Left }),
+ Right(resolveEdge = { Resolved.Right }),
+ Start(resolveEdge = { if (it == LayoutDirection.Ltr) Resolved.Left else Resolved.Right }),
+ End(resolveEdge = { if (it == LayoutDirection.Ltr) Resolved.Right else Resolved.Left });
+
+ override fun resolve(layoutDirection: LayoutDirection): Resolved {
+ return resolveEdge(layoutDirection)
+ }
+
+ enum class Resolved : SwipeSource.Resolved {
+ TopLeft,
+ TopRight,
+ Bottom,
+ Left,
+ Right,
+ }
+}
+
+/**
+ * A [SwipeSourceDetector] that detects edges similarly to [FixedSizeEdgeDetector], except that the
+ * top edge is split in two: top-left and top-right. The split point between the two is dynamic and
+ * may change during runtime.
+ *
+ * Callers who need to detect the start and end edges based on the layout direction (LTR vs RTL)
+ * should subscribe to [SceneContainerEdge.TopStart] and [SceneContainerEdge.TopEnd] instead. These
+ * will be resolved at runtime to [SceneContainerEdge.Resolved.TopLeft] and
+ * [SceneContainerEdge.Resolved.TopRight] appropriately. Similarly, [SceneContainerEdge.Start] and
+ * [SceneContainerEdge.End] will be resolved appropriately to [SceneContainerEdge.Resolved.Left] and
+ * [SceneContainerEdge.Resolved.Right].
+ *
+ * @param topEdgeSplitFraction A function which returns the fraction between [0..1] (i.e.,
+ * percentage) of screen width to consider the split point between "top-left" and "top-right"
+ * edges. It is called on each source detection event.
+ * @param edgeSize The fixed size of each edge.
+ */
+class SplitEdgeDetector(
+ val topEdgeSplitFraction: () -> Float,
+ val edgeSize: Dp,
+) : SwipeSourceDetector {
+
+ private val fixedEdgeDetector = FixedSizeEdgeDetector(edgeSize)
+
+ override fun source(
+ layoutSize: IntSize,
+ position: IntOffset,
+ density: Density,
+ orientation: Orientation,
+ ): SceneContainerEdge.Resolved? {
+ val fixedEdge =
+ fixedEdgeDetector.source(
+ layoutSize,
+ position,
+ density,
+ orientation,
+ )
+ return when (fixedEdge) {
+ Edge.Resolved.Top -> {
+ val topEdgeSplitFraction = topEdgeSplitFraction()
+ require(topEdgeSplitFraction in 0f..1f) {
+ "topEdgeSplitFraction must return a value between 0.0 and 1.0"
+ }
+ val isLeftSide = position.x < layoutSize.width * topEdgeSplitFraction
+ if (isLeftSide) SceneContainerEdge.Resolved.TopLeft
+ else SceneContainerEdge.Resolved.TopRight
+ }
+ Edge.Resolved.Left -> SceneContainerEdge.Resolved.Left
+ Edge.Resolved.Bottom -> SceneContainerEdge.Resolved.Bottom
+ Edge.Resolved.Right -> SceneContainerEdge.Resolved.Right
+ null -> null
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/UserActionsViewModel.kt
similarity index 91%
rename from packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModel.kt
rename to packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/UserActionsViewModel.kt
index 0766130..57628d0 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/UserActionsViewModel.kt
@@ -25,15 +25,13 @@
import kotlinx.coroutines.flow.asStateFlow
/**
- * Base class for view-models that need to keep a map of scene actions (also known as "destination
- * scenes") up-to-date.
+ * Base class for view-models that need to keep a map of user actions up-to-date.
*
* Subclasses need only to override [hydrateActions], suspending forever if they need; they don't
* need to worry about resetting the value of [actions] when the view-model is deactivated/canceled,
* this base class takes care of it.
*/
-// TODO(b/363206563): Rename to UserActionsViewModel.
-abstract class SceneActionsViewModel : ExclusiveActivatable() {
+abstract class UserActionsViewModel : ExclusiveActivatable() {
private val _actions = MutableStateFlow<Map<UserAction, UserActionResult>>(emptyMap())
/**
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java
index ad5e772..15a1d1d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java
@@ -68,6 +68,8 @@
import com.android.systemui.Flags;
import com.android.systemui.log.DebugLogger;
import com.android.systemui.res.R;
+import com.android.systemui.screenshot.appclips.InternalBacklinksData.BacklinksData;
+import com.android.systemui.screenshot.appclips.InternalBacklinksData.CrossProfileError;
import com.android.systemui.screenshot.scroll.CropView;
import com.android.systemui.settings.UserTracker;
@@ -100,6 +102,7 @@
private static final String TAG = AppClipsActivity.class.getSimpleName();
private static final ApplicationInfoFlags APPLICATION_INFO_FLAGS = ApplicationInfoFlags.of(0);
private static final int DRAWABLE_END = 2;
+ private static final float DISABLE_ALPHA = 0.5f;
private final AppClipsViewModel.Factory mViewModelFactory;
private final PackageManager mPackageManager;
@@ -116,6 +119,7 @@
private Button mCancel;
private CheckBox mBacklinksIncludeDataCheckBox;
private TextView mBacklinksDataTextView;
+ private TextView mBacklinksCrossProfileError;
private AppClipsViewModel mViewModel;
private ResultReceiver mResultReceiver;
@@ -192,8 +196,8 @@
mBacklinksDataTextView = mLayout.findViewById(R.id.backlinks_data);
mBacklinksIncludeDataCheckBox = mLayout.findViewById(R.id.backlinks_include_data);
mBacklinksIncludeDataCheckBox.setOnCheckedChangeListener(
- (buttonView, isChecked) ->
- mBacklinksDataTextView.setVisibility(isChecked ? View.VISIBLE : View.GONE));
+ this::backlinksIncludeDataCheckBoxCheckedChangeListener);
+ mBacklinksCrossProfileError = mLayout.findViewById(R.id.backlinks_cross_profile_error);
mViewModel = new ViewModelProvider(this, mViewModelFactory).get(AppClipsViewModel.class);
mViewModel.getScreenshot().observe(this, this::setScreenshot);
@@ -312,10 +316,11 @@
Intent.CAPTURE_CONTENT_FOR_NOTE_SUCCESS);
data.putParcelable(EXTRA_SCREENSHOT_URI, uri);
+ InternalBacklinksData selectedBacklink = mViewModel.mSelectedBacklinksLiveData.getValue();
if (mBacklinksIncludeDataCheckBox.getVisibility() == View.VISIBLE
&& mBacklinksIncludeDataCheckBox.isChecked()
- && mViewModel.mSelectedBacklinksLiveData.getValue() != null) {
- ClipData backlinksData = mViewModel.mSelectedBacklinksLiveData.getValue().getClipData();
+ && selectedBacklink instanceof BacklinksData) {
+ ClipData backlinksData = ((BacklinksData) selectedBacklink).getClipData();
data.putParcelable(EXTRA_CLIP_DATA, backlinksData);
DebugLogger.INSTANCE.logcatMessage(this,
@@ -459,6 +464,38 @@
mBacklinksDataTextView.setCompoundDrawablesRelative(/* start= */ appIcon, /* top= */
null, /* end= */ dropDownIcon, /* bottom= */ null);
+
+ updateViewsToShowOrHideBacklinkError(backlinksData);
+ }
+
+ /** Updates views to show or hide error with backlink. */
+ private void updateViewsToShowOrHideBacklinkError(InternalBacklinksData backlinksData) {
+ // Remove the check box change listener before updating it to avoid updating backlink text
+ // view visibility.
+ mBacklinksIncludeDataCheckBox.setOnCheckedChangeListener(null);
+ if (backlinksData instanceof CrossProfileError) {
+ // There's error with the backlink, unselect the checkbox and disable it.
+ mBacklinksIncludeDataCheckBox.setEnabled(false);
+ mBacklinksIncludeDataCheckBox.setChecked(false);
+ mBacklinksIncludeDataCheckBox.setAlpha(DISABLE_ALPHA);
+
+ mBacklinksCrossProfileError.setVisibility(View.VISIBLE);
+ } else {
+ // When there is no error, ensure the check box is enabled and checked.
+ mBacklinksIncludeDataCheckBox.setEnabled(true);
+ mBacklinksIncludeDataCheckBox.setChecked(true);
+ mBacklinksIncludeDataCheckBox.setAlpha(1.0f);
+
+ mBacklinksCrossProfileError.setVisibility(View.GONE);
+ }
+
+ // (Re)Set the check box change listener as we're done making changes to the check box.
+ mBacklinksIncludeDataCheckBox.setOnCheckedChangeListener(
+ this::backlinksIncludeDataCheckBoxCheckedChangeListener);
+ }
+
+ private void backlinksIncludeDataCheckBoxCheckedChangeListener(View unused, boolean isChecked) {
+ mBacklinksDataTextView.setVisibility(isChecked ? View.VISIBLE : View.GONE);
}
private Rect createBacklinksTextViewDrawableBounds() {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsViewModel.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsViewModel.java
index 3530b3f..9a38358 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsViewModel.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsViewModel.java
@@ -23,13 +23,13 @@
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
-import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.IActivityTaskManager;
import android.app.TaskInfo;
import android.app.WindowConfiguration;
import android.app.assist.AssistContent;
import android.content.ClipData;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
@@ -51,11 +51,14 @@
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
+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.log.DebugLogger;
import com.android.systemui.screenshot.AssistContentRequester;
import com.android.systemui.screenshot.ImageExporter;
+import com.android.systemui.screenshot.appclips.InternalBacklinksData.BacklinksData;
+import com.android.systemui.screenshot.appclips.InternalBacklinksData.CrossProfileError;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
@@ -82,7 +85,7 @@
private final ImageExporter mImageExporter;
private final IActivityTaskManager mAtmService;
private final AssistContentRequester mAssistContentRequester;
- private final PackageManager mPackageManager;
+ @Application private final Context mContext;
@Main
private final Executor mMainExecutor;
@@ -97,13 +100,13 @@
private AppClipsViewModel(AppClipsCrossProcessHelper appClipsCrossProcessHelper,
ImageExporter imageExporter, IActivityTaskManager atmService,
- AssistContentRequester assistContentRequester, PackageManager packageManager,
+ AssistContentRequester assistContentRequester, @Application Context context,
@Main Executor mainExecutor, @Background Executor bgExecutor) {
mAppClipsCrossProcessHelper = appClipsCrossProcessHelper;
mImageExporter = imageExporter;
mAtmService = atmService;
mAssistContentRequester = assistContentRequester;
- mPackageManager = packageManager;
+ mContext = context;
mMainExecutor = mainExecutor;
mBgExecutor = bgExecutor;
@@ -243,6 +246,10 @@
allTasksOnDisplay
.stream()
.filter(taskInfo -> shouldIncludeTask(taskInfo, taskIdsToIgnore))
+ .map(taskInfo -> new InternalTaskInfo(taskInfo.topActivityInfo,
+ taskInfo.taskId, taskInfo.userId,
+ getPackageManagerForUser(taskInfo.userId)))
+ .filter(this::canAppStartThroughLauncher)
.map(this::getBacklinksDataForTaskInfo)
.toList(),
mBgExecutor);
@@ -284,33 +291,34 @@
/**
* Returns whether the app represented by the provided {@link TaskInfo} should be included for
* querying for {@link AssistContent}.
+ *
+ * <p>This does not check whether the task has a launcher icon.
*/
private boolean shouldIncludeTask(TaskInfo taskInfo, Set<Integer> taskIdsToIgnore) {
DebugLogger.INSTANCE.logcatMessage(this,
() -> String.format("shouldIncludeTask taskId %d; topActivity %s", taskInfo.taskId,
taskInfo.topActivity));
- // Only consider tasks that shouldn't be ignored, are visible, running, and have a launcher
- // icon. Furthermore, types such as launcher/home/dock/assistant are ignored.
+ // Only consider tasks that shouldn't be ignored, are visible, and running. Furthermore,
+ // types such as launcher/home/dock/assistant are ignored.
return !taskIdsToIgnore.contains(taskInfo.taskId)
&& taskInfo.isVisible
&& taskInfo.isRunning
&& taskInfo.numActivities > 0
&& taskInfo.topActivity != null
&& taskInfo.topActivityInfo != null
- && taskInfo.getActivityType() == WindowConfiguration.ACTIVITY_TYPE_STANDARD
- && canAppStartThroughLauncher(taskInfo.topActivity.getPackageName());
+ && taskInfo.getActivityType() == WindowConfiguration.ACTIVITY_TYPE_STANDARD;
}
/**
- * Returns whether the app represented by the provided {@code packageName} can be launched
- * through the all apps tray by a user.
+ * Returns whether the app represented by the {@link InternalTaskInfo} can be launched through
+ * the all apps tray by a user.
*/
- private boolean canAppStartThroughLauncher(String packageName) {
+ private boolean canAppStartThroughLauncher(InternalTaskInfo internalTaskInfo) {
// Use Intent.resolveActivity API to check if the intent resolves as that is what Android
// uses internally when apps use Context.startActivity.
- return getMainLauncherIntentForPackage(packageName).resolveActivity(mPackageManager)
- != null;
+ return getMainLauncherIntentForTask(internalTaskInfo)
+ .resolveActivity(internalTaskInfo.getPackageManager()) != null;
}
/**
@@ -318,18 +326,36 @@
* is captured by querying the system using {@link TaskInfo#taskId}.
*/
private ListenableFuture<InternalBacklinksData> getBacklinksDataForTaskInfo(
- TaskInfo taskInfo) {
+ InternalTaskInfo internalTaskInfo) {
DebugLogger.INSTANCE.logcatMessage(this,
() -> String.format("getBacklinksDataForTaskId for taskId %d; topActivity %s",
- taskInfo.taskId, taskInfo.topActivity));
+ internalTaskInfo.getTaskId(),
+ internalTaskInfo.getTopActivityNameForDebugLogging()));
+
+ // Unlike other SysUI components, App Clips is started by the notes app so it runs as the
+ // same user as the notes app. That is, if the notes app was running as work profile user
+ // then App Clips also runs as work profile user. This is why while checking for user of the
+ // screenshotted app the check is performed using UserHandle.myUserId instead of using the
+ // more complex UserTracker.
+ if (internalTaskInfo.getUserId() != UserHandle.myUserId()) {
+ return getCrossProfileErrorBacklinkForTask(internalTaskInfo);
+ }
SettableFuture<InternalBacklinksData> backlinksData = SettableFuture.create();
- int taskId = taskInfo.taskId;
- mAssistContentRequester.requestAssistContent(taskId, assistContent ->
- backlinksData.set(getBacklinksDataFromAssistContent(taskInfo, assistContent)));
+ int taskId = internalTaskInfo.getTaskId();
+ mAssistContentRequester.requestAssistContent(taskId, assistContent -> backlinksData.set(
+ getBacklinksDataFromAssistContent(internalTaskInfo, assistContent)));
return withTimeout(backlinksData);
}
+ private ListenableFuture<InternalBacklinksData> getCrossProfileErrorBacklinkForTask(
+ InternalTaskInfo internalTaskInfo) {
+ String appName = internalTaskInfo.getTopActivityAppName();
+ Drawable appIcon = internalTaskInfo.getTopActivityAppIcon();
+ InternalBacklinksData errorData = new CrossProfileError(appIcon, appName);
+ return Futures.immediateFuture(errorData);
+ }
+
/** Returns the same {@link ListenableFuture} but with a 5 {@link TimeUnit#SECONDS} timeout. */
private static <V> ListenableFuture<V> withTimeout(ListenableFuture<V> future) {
return Futures.withTimeout(future, 5L, TimeUnit.SECONDS,
@@ -351,22 +377,24 @@
* {@link Intent#ACTION_MAIN} and {@link Intent#CATEGORY_LAUNCHER}.
* </ul>
*
- * @param taskInfo {@link RootTaskInfo} of the task which provided the {@link AssistContent}.
+ * @param internalTaskInfo {@link InternalTaskInfo} of the task which provided the
+ * {@link AssistContent}.
* @param content the {@link AssistContent} to map into Backlinks {@link ClipData}.
* @return {@link InternalBacklinksData} that represents the Backlinks data along with app icon.
*/
- private InternalBacklinksData getBacklinksDataFromAssistContent(TaskInfo taskInfo,
+ private InternalBacklinksData getBacklinksDataFromAssistContent(
+ InternalTaskInfo internalTaskInfo,
@Nullable AssistContent content) {
DebugLogger.INSTANCE.logcatMessage(this,
() -> String.format("getBacklinksDataFromAssistContent taskId %d; topActivity %s",
- taskInfo.taskId, taskInfo.topActivity));
+ internalTaskInfo.getTaskId(),
+ internalTaskInfo.getTopActivityNameForDebugLogging()));
- String appName = getAppNameOfTask(taskInfo);
- String packageName = taskInfo.topActivity.getPackageName();
- Drawable appIcon = taskInfo.topActivityInfo.loadIcon(mPackageManager);
+ String appName = internalTaskInfo.getTopActivityAppName();
+ Drawable appIcon = internalTaskInfo.getTopActivityAppIcon();
ClipData mainLauncherIntent = ClipData.newIntent(appName,
- getMainLauncherIntentForPackage(packageName));
- InternalBacklinksData fallback = new InternalBacklinksData(mainLauncherIntent, appIcon);
+ getMainLauncherIntentForTask(internalTaskInfo));
+ InternalBacklinksData fallback = new BacklinksData(mainLauncherIntent, appIcon);
if (content == null) {
return fallback;
}
@@ -378,10 +406,10 @@
Uri uri = content.getWebUri();
Intent backlinksIntent = new Intent(ACTION_VIEW).setData(uri);
- if (doesIntentResolveToSamePackage(backlinksIntent, packageName)) {
+ if (doesIntentResolveToSameTask(backlinksIntent, internalTaskInfo)) {
DebugLogger.INSTANCE.logcatMessage(this,
() -> "getBacklinksDataFromAssistContent: using app provided uri");
- return new InternalBacklinksData(ClipData.newRawUri(appName, uri), appIcon);
+ return new BacklinksData(ClipData.newRawUri(appName, uri), appIcon);
}
}
@@ -391,11 +419,10 @@
() -> "getBacklinksDataFromAssistContent: app has provided an intent");
Intent backlinksIntent = content.getIntent();
- if (doesIntentResolveToSamePackage(backlinksIntent, packageName)) {
+ if (doesIntentResolveToSameTask(backlinksIntent, internalTaskInfo)) {
DebugLogger.INSTANCE.logcatMessage(this,
() -> "getBacklinksDataFromAssistContent: using app provided intent");
- return new InternalBacklinksData(ClipData.newIntent(appName, backlinksIntent),
- appIcon);
+ return new BacklinksData(ClipData.newIntent(appName, backlinksIntent), appIcon);
}
}
@@ -404,28 +431,28 @@
return fallback;
}
- private boolean doesIntentResolveToSamePackage(Intent intentToResolve,
- String requiredPackageName) {
- ComponentName resolvedComponent = intentToResolve.resolveActivity(mPackageManager);
+ private boolean doesIntentResolveToSameTask(Intent intentToResolve,
+ InternalTaskInfo requiredTaskInfo) {
+ PackageManager packageManager = requiredTaskInfo.getPackageManager();
+ ComponentName resolvedComponent = intentToResolve.resolveActivity(packageManager);
if (resolvedComponent == null) {
return false;
}
+ String requiredPackageName = requiredTaskInfo.getTopActivityPackageName();
return resolvedComponent.getPackageName().equals(requiredPackageName);
}
- private String getAppNameOfTask(TaskInfo taskInfo) {
- return taskInfo.topActivityInfo.loadLabel(mPackageManager).toString();
- }
-
- private Intent getMainLauncherIntentForPackage(String pkgName) {
+ private Intent getMainLauncherIntentForTask(InternalTaskInfo internalTaskInfo) {
+ String pkgName = internalTaskInfo.getTopActivityPackageName();
Intent intent = new Intent(ACTION_MAIN).addCategory(CATEGORY_LAUNCHER).setPackage(pkgName);
// Not all apps use DEFAULT_CATEGORY for their main launcher activity so the exact component
// needs to be queried and set on the Intent in order for note-taking apps to be able to
// start this intent. When starting an activity with an implicit intent, Android adds the
// DEFAULT_CATEGORY flag otherwise it fails to resolve the intent.
- ResolveInfo resolvedActivity = mPackageManager.resolveActivity(intent, /* flags= */ 0);
+ PackageManager packageManager = internalTaskInfo.getPackageManager();
+ ResolveInfo resolvedActivity = packageManager.resolveActivity(intent, /* flags= */ 0);
if (resolvedActivity != null) {
intent.setComponent(resolvedActivity.getComponentInfo().getComponentName());
}
@@ -433,6 +460,17 @@
return intent;
}
+ private PackageManager getPackageManagerForUser(int userId) {
+ // If app clips was launched as the same user, then reuse the available PM from mContext.
+ if (mContext.getUserId() == userId) {
+ return mContext.getPackageManager();
+ }
+
+ // PackageManager required for a different user, create its context and return its PM.
+ UserHandle userHandle = UserHandle.of(userId);
+ return mContext.createContextAsUser(userHandle, /* flags= */ 0).getPackageManager();
+ }
+
/** Helper factory to help with injecting {@link AppClipsViewModel}. */
static final class Factory implements ViewModelProvider.Factory {
@@ -440,7 +478,7 @@
private final ImageExporter mImageExporter;
private final IActivityTaskManager mAtmService;
private final AssistContentRequester mAssistContentRequester;
- private final PackageManager mPackageManager;
+ @Application private final Context mContext;
@Main
private final Executor mMainExecutor;
@Background
@@ -449,13 +487,13 @@
@Inject
Factory(AppClipsCrossProcessHelper appClipsCrossProcessHelper, ImageExporter imageExporter,
IActivityTaskManager atmService, AssistContentRequester assistContentRequester,
- PackageManager packageManager, @Main Executor mainExecutor,
+ @Application Context context, @Main Executor mainExecutor,
@Background Executor bgExecutor) {
mAppClipsCrossProcessHelper = appClipsCrossProcessHelper;
mImageExporter = imageExporter;
mAtmService = atmService;
mAssistContentRequester = assistContentRequester;
- mPackageManager = packageManager;
+ mContext = context;
mMainExecutor = mainExecutor;
mBgExecutor = bgExecutor;
}
@@ -469,7 +507,7 @@
//noinspection unchecked
return (T) new AppClipsViewModel(mAppClipsCrossProcessHelper, mImageExporter,
- mAtmService, mAssistContentRequester, mPackageManager, mMainExecutor,
+ mAtmService, mAssistContentRequester, mContext, mMainExecutor,
mBgExecutor);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/InternalBacklinksData.kt b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/InternalBacklinksData.kt
index 30c33c5..234692e 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/InternalBacklinksData.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/InternalBacklinksData.kt
@@ -16,10 +16,49 @@
package com.android.systemui.screenshot.appclips
+import android.app.TaskInfo
import android.content.ClipData
+import android.content.pm.ActivityInfo
+import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
-/** A class to hold the [ClipData] for backlinks and the corresponding app's [Drawable] icon. */
-internal data class InternalBacklinksData(val clipData: ClipData, val appIcon: Drawable) {
- var displayLabel: String = clipData.description.label.toString()
+/**
+ * A class to hold the [ClipData] for backlinks, the corresponding app's [Drawable] icon, and
+ * represent error when necessary.
+ */
+internal sealed class InternalBacklinksData(
+ open val appIcon: Drawable,
+ open var displayLabel: String
+) {
+ data class BacklinksData(val clipData: ClipData, override val appIcon: Drawable) :
+ InternalBacklinksData(appIcon, clipData.description.label.toString())
+
+ data class CrossProfileError(
+ override val appIcon: Drawable,
+ override var displayLabel: String
+ ) : InternalBacklinksData(appIcon, displayLabel)
+}
+
+/**
+ * A class to hold important members of [TaskInfo] and its associated user's [PackageManager] for
+ * ease of querying.
+ *
+ * @note A task can have a different app running on top. For example, an app "A" can use camera app
+ * to capture an image. In this case the top app will be the camera app even though the task
+ * belongs to app A. This is expected behaviour because user will be taking a screenshot of the
+ * content rendered by the camera (top) app.
+ */
+internal data class InternalTaskInfo(
+ private val topActivityInfo: ActivityInfo,
+ val taskId: Int,
+ val userId: Int,
+ val packageManager: PackageManager
+) {
+ fun getTopActivityNameForDebugLogging(): String = topActivityInfo.name
+
+ fun getTopActivityPackageName(): String = topActivityInfo.packageName
+
+ fun getTopActivityAppName(): String = topActivityInfo.loadLabel(packageManager).toString()
+
+ fun getTopActivityAppIcon(): Drawable = topActivityInfo.loadIcon(packageManager)
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
index ed590c3..553d1f5 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -103,11 +103,8 @@
override val userContentResolver: ContentResolver
get() = userContext.contentResolver
- override val userInfo: UserInfo
- get() {
- val user = userId
- return userProfiles.first { it.id == user }
- }
+ override var userInfo: UserInfo by SynchronizedDelegate(UserInfo(context.userId, "", 0))
+ protected set
/**
* Returns a [List<UserInfo>] of all profiles associated with the current user.
@@ -187,6 +184,7 @@
userHandle = handle
userContext = ctx
userProfiles = profiles.map { UserInfo(it) }
+ userInfo = profiles.first { it.id == user }
}
return ctx to profiles
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
index 3bb494b..7fa9926 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
@@ -96,7 +96,7 @@
private val lockscreenSmartspaceController: LockscreenSmartspaceController,
@CommunalTouchLog logBuffer: LogBuffer,
) : LifecycleOwner {
- private val logger = Logger(logBuffer, "GlanceableHubContainerController")
+ private val logger = Logger(logBuffer, TAG)
private class CommunalWrapper(context: Context) : FrameLayout(context) {
private val consumers: MutableSet<Consumer<Boolean>> = ArraySet()
@@ -301,7 +301,7 @@
if (touchMonitor == null) {
touchMonitor =
- ambientTouchComponentFactory.create(this, HashSet()).getTouchMonitor().apply {
+ ambientTouchComponentFactory.create(this, HashSet(), TAG).getTouchMonitor().apply {
init()
}
}
@@ -508,6 +508,11 @@
fun onTouchEvent(ev: MotionEvent): Boolean {
SceneContainerFlag.assertInLegacyMode()
+ if (communalContainerView == null) {
+ // Return early so we don't log unnecessarily and fill up our LogBuffer.
+ return false
+ }
+
// In the case that we are handling full swipes on the lockscreen, are on the lockscreen,
// and the touch is within the horizontal notification band on the screen, do not process
// the touch.
@@ -528,7 +533,7 @@
return false
}
- return communalContainerView?.let { handleTouchEventOnCommunalView(ev) } ?: false
+ return handleTouchEventOnCommunalView(ev)
}
private fun handleTouchEventOnCommunalView(ev: MotionEvent): Boolean {
@@ -630,4 +635,8 @@
override val lifecycle: Lifecycle
get() = lifecycleRegistry
+
+ companion object {
+ private const val TAG = "GlanceableHubContainer"
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index 7e0454c..3f3ad13 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -49,6 +49,7 @@
import com.android.systemui.Dumpable;
import com.android.systemui.Flags;
import com.android.systemui.biometrics.AuthController;
+import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.communal.domain.interactor.CommunalInteractor;
import com.android.systemui.dagger.SysUISingleton;
@@ -342,6 +343,12 @@
this::setKeyguardOccluded
);
}
+ if (ComposeBouncerFlags.INSTANCE.isComposeBouncerOrSceneContainerEnabled()) {
+ collectFlow(mWindowRootView, mNotificationShadeWindowModel.isBouncerShowing(),
+ this::setBouncerShowing);
+ collectFlow(mWindowRootView, mNotificationShadeWindowModel.getDoesBouncerRequireIme(),
+ this::setKeyguardNeedsInput);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
index 830649b..4ed4af6 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
@@ -42,6 +42,7 @@
import android.util.MathUtils;
import android.view.MotionEvent;
import android.view.VelocityTracker;
+import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowInsets;
@@ -463,6 +464,9 @@
mJavaAdapter.alwaysCollectFlow(
mCommunalTransitionViewModelLazy.get().isUmoOnCommunal(),
this::setShouldUpdateSquishinessOnMedia);
+ mJavaAdapter.alwaysCollectFlow(
+ mShadeInteractor.isAnyExpanded(),
+ this::onAnyExpandedChanged);
}
private void initNotificationStackScrollLayoutController() {
@@ -482,6 +486,10 @@
}
}
+ private void onAnyExpandedChanged(boolean isAnyExpanded) {
+ mQsFrame.setVisibility(isAnyExpanded ? View.VISIBLE : View.INVISIBLE);
+ }
+
private void onNotificationScrolled(int newScrollPosition) {
updateExpansionEnabledAmbient();
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
index 73e86a2..3cd91be 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
@@ -16,6 +16,7 @@
package com.android.systemui.shade.domain.interactor
+import androidx.annotation.FloatRange
import com.android.systemui.shade.shared.model.ShadeMode
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
@@ -69,6 +70,20 @@
* wide as the entire screen.
*/
val isShadeLayoutWide: StateFlow<Boolean>
+
+ /**
+ * The fraction between [0..1] (i.e., percentage) of screen width to consider the threshold
+ * between "top-left" and "top-right" for the purposes of dual-shade invocation.
+ *
+ * When the dual-shade is not wide, this always returns 0.5 (the top edge is evenly split). On
+ * wide layouts however, a larger fraction is returned because only the area of the system
+ * status icons is considered top-right.
+ *
+ * Note that this fraction only determines the split between the absolute left and right
+ * directions. In RTL layouts, the "top-start" edge will resolve to "top-right", and "top-end"
+ * will resolve to "top-left".
+ */
+ @FloatRange(from = 0.0, to = 1.0) fun getTopEdgeSplitFraction(): Float
}
/** ShadeInteractor methods with implementations that differ between non-empty impls. */
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt
index d51fd28..6c0b55a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt
@@ -47,4 +47,6 @@
override val isExpandToQsEnabled: Flow<Boolean> = inactiveFlowBoolean
override val shadeMode: StateFlow<ShadeMode> = MutableStateFlow(ShadeMode.Single)
override val isShadeLayoutWide: StateFlow<Boolean> = inactiveFlowBoolean
+
+ override fun getTopEdgeSplitFraction(): Float = 0.5f
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt
index 3552092..b8d2dd2 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt
@@ -16,6 +16,7 @@
package com.android.systemui.shade.domain.interactor
+import androidx.annotation.FloatRange
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardRepository
@@ -104,6 +105,16 @@
override val isShadeLayoutWide: StateFlow<Boolean> = shadeRepository.isShadeLayoutWide
+ @FloatRange(from = 0.0, to = 1.0)
+ override fun getTopEdgeSplitFraction(): Float {
+ // Note: this implicitly relies on isShadeLayoutWide being hot (i.e. collected). This
+ // assumption allows us to query its value on demand (during swipe source detection) instead
+ // of running another infinite coroutine.
+ // TODO(b/338577208): Instead of being fixed at 0.8f, this should dynamically updated based
+ // on the position of system-status icons in the status bar.
+ return if (shadeRepository.isShadeLayoutWide.value) 0.8f else 0.5f
+ }
+
override val shadeMode: StateFlow<ShadeMode> =
isShadeLayoutWide
.map(this::determineShadeMode)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModel.kt
index 9c4bf1f..9655d92 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModel.kt
@@ -16,16 +16,25 @@
package com.android.systemui.shade.ui.viewmodel
+import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB
import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED
+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.util.kotlin.BooleanFlowOperators.any
+import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
/** Models UI state for the shade window. */
@@ -34,6 +43,9 @@
@Inject
constructor(
keyguardTransitionInteractor: KeyguardTransitionInteractor,
+ sceneInteractor: dagger.Lazy<SceneInteractor>,
+ authenticationInteractor: dagger.Lazy<AuthenticationInteractor>,
+ primaryBouncerInteractor: PrimaryBouncerInteractor,
) {
/**
* Considered to be occluded if in OCCLUDED, DREAMING, GLANCEABLE_HUB/Communal, or transitioning
@@ -70,4 +82,53 @@
),
)
.any()
+
+ /**
+ * Whether bouncer is currently showing or not.
+ *
+ * Applicable only when either [SceneContainerFlag] or [ComposeBouncerFlags] are enabled,
+ * otherwise it throws an error.
+ */
+ val isBouncerShowing: Flow<Boolean> =
+ when {
+ SceneContainerFlag.isEnabled -> {
+ sceneInteractor.get().transitionState.map { it.isIdle(Scenes.Bouncer) }
+ }
+ ComposeBouncerFlags.isOnlyComposeBouncerEnabled() -> primaryBouncerInteractor.isShowing
+ else ->
+ flow {
+ error(
+ "Consume this flow only when SceneContainerFlag " +
+ "or ComposeBouncerFlags are enabled"
+ )
+ }
+ }.distinctUntilChanged()
+
+ /**
+ * Whether the bouncer currently require IME for device entry.
+ *
+ * This emits true when the authentication method is set to password and the bouncer is
+ * currently showing. Throws an error when this is used without either [SceneContainerFlag] or
+ * [ComposeBouncerFlags]
+ */
+ val doesBouncerRequireIme: Flow<Boolean> =
+ if (ComposeBouncerFlags.isComposeBouncerOrSceneContainerEnabled()) {
+ // This is required to make the window, where the bouncer resides,
+ // focusable. InputMethodManager allows IME to be shown only for views
+ // in windows that do not have the FLAG_NOT_FOCUSABLE flag.
+
+ isBouncerShowing
+ .sample(authenticationInteractor.get().authenticationMethod, ::Pair)
+ .map { (showing, authMethod) ->
+ showing && authMethod == AuthenticationMethodModel.Password
+ }
+ } else {
+ flow {
+ error(
+ "Consume this flow only when SceneContainerFlag " +
+ "or ComposeBouncerFlags are enabled"
+ )
+ }
+ }
+ .distinctUntilChanged()
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt
index 7c70759..ce4c081 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt
@@ -43,7 +43,7 @@
/**
* Models UI state used to render the content of the shade scene.
*
- * Different from [ShadeSceneActionsViewModel], which only models user actions that can be performed
+ * Different from [ShadeUserActionsViewModel], which only models user actions that can be performed
* to navigate to other scenes.
*/
class ShadeSceneContentViewModel
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModel.kt
similarity index 93%
rename from packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModel.kt
rename to packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModel.kt
index ab71913..f8a850a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModel.kt
@@ -24,7 +24,7 @@
import com.android.systemui.scene.shared.model.SceneFamilies
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.TransitionKeys.ToSplitShade
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.shared.model.ShadeMode
import dagger.assisted.AssistedFactory
@@ -36,12 +36,12 @@
*
* Different from the [ShadeSceneContentViewModel] which models the _content_ of the scene.
*/
-class ShadeSceneActionsViewModel
+class ShadeUserActionsViewModel
@AssistedInject
constructor(
private val qsSceneAdapter: QSSceneAdapter,
private val shadeInteractor: ShadeInteractor,
-) : SceneActionsViewModel() {
+) : UserActionsViewModel() {
override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
combine(
@@ -71,6 +71,6 @@
@AssistedFactory
interface Factory {
- fun create(): ShadeSceneActionsViewModel
+ fun create(): ShadeUserActionsViewModel
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/smartspace/config/BcSmartspaceConfigProvider.kt b/packages/SystemUI/src/com/android/systemui/smartspace/config/BcSmartspaceConfigProvider.kt
index 922560f..0e1bf72 100644
--- a/packages/SystemUI/src/com/android/systemui/smartspace/config/BcSmartspaceConfigProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/smartspace/config/BcSmartspaceConfigProvider.kt
@@ -16,6 +16,7 @@
package com.android.systemui.smartspace.config
+import com.android.systemui.Flags.smartspaceViewpager2
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.plugins.BcSmartspaceConfigPlugin
@@ -23,4 +24,7 @@
BcSmartspaceConfigPlugin {
override val isDefaultDateWeatherDisabled: Boolean
get() = true
+
+ override val isViewPager2Enabled: Boolean
+ get() = smartspaceViewpager2()
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ImmersiveModeConfirmation.java b/packages/SystemUI/src/com/android/systemui/statusbar/ImmersiveModeConfirmation.java
index 2b9daef..5ef5a7d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ImmersiveModeConfirmation.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ImmersiveModeConfirmation.java
@@ -79,6 +79,7 @@
import com.android.app.viewcapture.ViewCapture;
import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
import com.android.systemui.CoreStartable;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.res.R;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -107,6 +108,7 @@
private Context mDisplayContext;
private final Context mSysUiContext;
private final Handler mHandler = new H(Looper.getMainLooper());
+ private final Handler mBackgroundHandler;
private long mShowDelayMs = 0L;
private final IBinder mWindowToken = new Binder();
private final CommandQueue mCommandQueue;
@@ -139,7 +141,8 @@
@Inject
public ImmersiveModeConfirmation(Context context, CommandQueue commandQueue,
SecureSettings secureSettings,
- dagger.Lazy<ViewCapture> daggerLazyViewCapture) {
+ dagger.Lazy<ViewCapture> daggerLazyViewCapture,
+ @Background Handler backgroundHandler) {
mSysUiContext = context;
final Display display = mSysUiContext.getDisplay();
mDisplayContext = display.getDisplayId() == DEFAULT_DISPLAY
@@ -147,6 +150,7 @@
mCommandQueue = commandQueue;
mSecureSettings = secureSettings;
mLazyViewCapture = toKotlinLazy(daggerLazyViewCapture);
+ mBackgroundHandler = backgroundHandler;
}
boolean loadSetting(int currentUserId) {
@@ -329,7 +333,7 @@
}
}
TaskStackChangeListeners.getInstance().registerTaskStackListener(this);
- mContentObserver = new ContentObserver(mHandler) {
+ mContentObserver = new ContentObserver(mBackgroundHandler) {
@Override
public void onChange(boolean selfChange) {
onSettingChanged(mSysUiContext.getUserId());
@@ -343,6 +347,9 @@
mSecureSettings.registerContentObserverForUserSync(
Settings.Secure.USER_SETUP_COMPLETE, mContentObserver,
UserHandle.USER_CURRENT);
+ mBackgroundHandler.post(() -> {
+ loadSetting(UserHandle.USER_CURRENT);
+ });
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
index 64dfc6c..735b4c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
@@ -54,6 +54,8 @@
VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
+ private static final VibrationAttributes COMMUNICATION_REQUEST_VIBRATION_ATTRIBUTES =
+ VibrationAttributes.createForUsage(VibrationAttributes.USAGE_COMMUNICATION_REQUEST);
private final Executor mExecutor;
@@ -151,7 +153,7 @@
vibrate(Process.myUid(),
"com.android.systemui",
BIOMETRIC_SUCCESS_VIBRATION_EFFECT, reason,
- HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES);
+ COMMUNICATION_REQUEST_VIBRATION_ATTRIBUTES);
}
/**
@@ -160,7 +162,7 @@
public void vibrateAuthError(String reason) {
vibrate(Process.myUid(), "com.android.systemui",
BIOMETRIC_ERROR_VIBRATION_EFFECT, reason,
- HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES);
+ COMMUNICATION_REQUEST_VIBRATION_ATTRIBUTES);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
new file mode 100644
index 0000000..3b1e565
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
@@ -0,0 +1,314 @@
+/*
+ * 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.statusbar.chips.ui.binder
+
+import android.annotation.IdRes
+import android.content.res.ColorStateList
+import android.graphics.drawable.GradientDrawable
+import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import android.widget.ImageView
+import android.widget.TextView
+import com.android.systemui.common.ui.binder.IconViewBinder
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.StatusBarIconView
+import com.android.systemui.statusbar.chips.ron.shared.StatusBarRonChips
+import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
+import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
+import com.android.systemui.statusbar.chips.ui.view.ChipChronometer
+
+/** Binder for ongoing activity chip views. */
+object OngoingActivityChipBinder {
+ /** Binds the given [chipModel] data to the given [chipView]. */
+ fun bind(chipModel: OngoingActivityChipModel, chipView: View) {
+ val chipContext = chipView.context
+ val chipDefaultIconView: ImageView =
+ chipView.requireViewById(R.id.ongoing_activity_chip_icon)
+ val chipTimeView: ChipChronometer =
+ chipView.requireViewById(R.id.ongoing_activity_chip_time)
+ val chipTextView: TextView = chipView.requireViewById(R.id.ongoing_activity_chip_text)
+ val chipBackgroundView: ChipBackgroundContainer =
+ chipView.requireViewById(R.id.ongoing_activity_chip_background)
+
+ when (chipModel) {
+ is OngoingActivityChipModel.Shown -> {
+ // Data
+ setChipIcon(chipModel, chipBackgroundView, chipDefaultIconView)
+ setChipMainContent(chipModel, chipTextView, chipTimeView)
+ chipView.setOnClickListener(chipModel.onClickListener)
+ updateChipPadding(
+ chipModel,
+ chipBackgroundView,
+ chipTextView,
+ chipTimeView,
+ )
+
+ // Accessibility
+ setChipAccessibility(chipModel, chipView, chipBackgroundView)
+
+ // Colors
+ val textColor = chipModel.colors.text(chipContext)
+ chipTimeView.setTextColor(textColor)
+ chipTextView.setTextColor(textColor)
+ (chipBackgroundView.background as GradientDrawable).color =
+ chipModel.colors.background(chipContext)
+ }
+ is OngoingActivityChipModel.Hidden -> {
+ // The Chronometer should be stopped to prevent leaks -- see b/192243808 and
+ // [Chronometer.start].
+ chipTimeView.stop()
+ }
+ }
+ }
+
+ private fun setChipIcon(
+ chipModel: OngoingActivityChipModel.Shown,
+ backgroundView: ChipBackgroundContainer,
+ defaultIconView: ImageView,
+ ) {
+ // Always remove any previously set custom icon. If we have a new custom icon, we'll re-add
+ // it.
+ backgroundView.removeView(backgroundView.getCustomIconView())
+
+ val iconTint = chipModel.colors.text(defaultIconView.context)
+
+ when (val icon = chipModel.icon) {
+ null -> {
+ defaultIconView.visibility = View.GONE
+ }
+ is OngoingActivityChipModel.ChipIcon.SingleColorIcon -> {
+ IconViewBinder.bind(icon.impl, defaultIconView)
+ defaultIconView.visibility = View.VISIBLE
+ defaultIconView.tintView(iconTint)
+ }
+ is OngoingActivityChipModel.ChipIcon.FullColorAppIcon -> {
+ StatusBarRonChips.assertInNewMode()
+ IconViewBinder.bind(icon.impl, defaultIconView)
+ defaultIconView.visibility = View.VISIBLE
+ defaultIconView.untintView()
+ }
+ is OngoingActivityChipModel.ChipIcon.StatusBarView -> {
+ // Hide the default icon since we'll show this custom icon instead.
+ defaultIconView.visibility = View.GONE
+
+ // Add the new custom icon:
+ // 1. Set up the right visual params.
+ val iconView = icon.impl
+ with(iconView) {
+ id = CUSTOM_ICON_VIEW_ID
+ // TODO(b/354930838): Update the content description to not include "phone" and
+ // maybe include the app name.
+ contentDescription =
+ context.resources.getString(R.string.ongoing_phone_call_content_description)
+ tintView(iconTint)
+ }
+
+ // 2. If we just reinflated the view, we may need to detach the icon view from the
+ // old chip before we reattach it to the new one.
+ // See also: NotificationIconContainerViewBinder#bindIcons.
+ val currentParent = iconView.parent as? ViewGroup
+ if (currentParent != null && currentParent != backgroundView) {
+ currentParent.removeView(iconView)
+ currentParent.removeTransientView(iconView)
+ }
+
+ // 3: Add the icon as the starting view.
+ backgroundView.addView(
+ iconView,
+ /* index= */ 0,
+ generateCustomIconLayoutParams(iconView),
+ )
+ }
+ }
+ }
+
+ private fun View.getCustomIconView(): StatusBarIconView? {
+ return this.findViewById(CUSTOM_ICON_VIEW_ID)
+ }
+
+ private fun ImageView.tintView(color: Int) {
+ this.imageTintList = ColorStateList.valueOf(color)
+ }
+
+ private fun ImageView.untintView() {
+ this.imageTintList = null
+ }
+
+ private fun generateCustomIconLayoutParams(iconView: ImageView): FrameLayout.LayoutParams {
+ val customIconSize =
+ iconView.context.resources.getDimensionPixelSize(
+ R.dimen.ongoing_activity_chip_embedded_padding_icon_size
+ )
+ return FrameLayout.LayoutParams(customIconSize, customIconSize)
+ }
+
+ private fun setChipMainContent(
+ chipModel: OngoingActivityChipModel.Shown,
+ chipTextView: TextView,
+ chipTimeView: ChipChronometer,
+ ) {
+ when (chipModel) {
+ is OngoingActivityChipModel.Shown.Countdown -> {
+ chipTextView.text = chipModel.secondsUntilStarted.toString()
+ chipTextView.visibility = View.VISIBLE
+
+ chipTimeView.hide()
+ }
+ is OngoingActivityChipModel.Shown.Text -> {
+ chipTextView.text = chipModel.text
+ chipTextView.visibility = View.VISIBLE
+
+ chipTimeView.hide()
+ }
+ is OngoingActivityChipModel.Shown.Timer -> {
+ ChipChronometerBinder.bind(chipModel.startTimeMs, chipTimeView)
+ chipTimeView.visibility = View.VISIBLE
+
+ chipTextView.visibility = View.GONE
+ }
+ is OngoingActivityChipModel.Shown.IconOnly -> {
+ chipTextView.visibility = View.GONE
+ chipTimeView.hide()
+ }
+ }
+ }
+
+ private fun ChipChronometer.hide() {
+ // The Chronometer should be stopped to prevent leaks -- see b/192243808 and
+ // [Chronometer.start].
+ this.stop()
+ this.visibility = View.GONE
+ }
+
+ private fun updateChipPadding(
+ chipModel: OngoingActivityChipModel.Shown,
+ backgroundView: View,
+ chipTextView: TextView,
+ chipTimeView: ChipChronometer,
+ ) {
+ if (chipModel.icon != null) {
+ if (chipModel.icon is OngoingActivityChipModel.ChipIcon.StatusBarView) {
+ // If the icon is a custom [StatusBarIconView], then it should've come from
+ // `Notification.smallIcon`, which is required to embed its own paddings. We need to
+ // adjust the other paddings to make everything look good :)
+ backgroundView.setBackgroundPaddingForEmbeddedPaddingIcon()
+ chipTextView.setTextPaddingForEmbeddedPaddingIcon()
+ chipTimeView.setTextPaddingForEmbeddedPaddingIcon()
+ } else {
+ backgroundView.setBackgroundPaddingForNormalIcon()
+ chipTextView.setTextPaddingForNormalIcon()
+ chipTimeView.setTextPaddingForNormalIcon()
+ }
+ } else {
+ backgroundView.setBackgroundPaddingForNoIcon()
+ chipTextView.setTextPaddingForNoIcon()
+ chipTimeView.setTextPaddingForNoIcon()
+ }
+ }
+
+ private fun View.setTextPaddingForEmbeddedPaddingIcon() {
+ val newPaddingEnd =
+ context.resources.getDimensionPixelSize(
+ R.dimen.ongoing_activity_chip_text_end_padding_for_embedded_padding_icon
+ )
+ setPaddingRelative(
+ // The icon should embed enough padding between the icon and time view.
+ /* start= */ 0,
+ this.paddingTop,
+ newPaddingEnd,
+ this.paddingBottom,
+ )
+ }
+
+ private fun View.setTextPaddingForNormalIcon() {
+ this.setPaddingRelative(
+ this.context.resources.getDimensionPixelSize(
+ R.dimen.ongoing_activity_chip_icon_text_padding
+ ),
+ paddingTop,
+ // The background view will contain the right end padding.
+ /* end= */ 0,
+ paddingBottom,
+ )
+ }
+
+ private fun View.setTextPaddingForNoIcon() {
+ // The background view will have even start & end paddings, so we don't want the text view
+ // to add any additional padding.
+ this.setPaddingRelative(/* start= */ 0, paddingTop, /* end= */ 0, paddingBottom)
+ }
+
+ private fun View.setBackgroundPaddingForEmbeddedPaddingIcon() {
+ val sidePadding =
+ context.resources.getDimensionPixelSize(
+ R.dimen.ongoing_activity_chip_side_padding_for_embedded_padding_icon
+ )
+ setPaddingRelative(
+ sidePadding,
+ paddingTop,
+ sidePadding,
+ paddingBottom,
+ )
+ }
+
+ private fun View.setBackgroundPaddingForNormalIcon() {
+ val sidePadding =
+ context.resources.getDimensionPixelSize(R.dimen.ongoing_activity_chip_side_padding)
+ setPaddingRelative(
+ sidePadding,
+ paddingTop,
+ sidePadding,
+ paddingBottom,
+ )
+ }
+
+ private fun View.setBackgroundPaddingForNoIcon() {
+ // The padding for the normal icon is also appropriate for no icon.
+ setBackgroundPaddingForNormalIcon()
+ }
+
+ private fun setChipAccessibility(
+ chipModel: OngoingActivityChipModel.Shown,
+ chipView: View,
+ chipBackgroundView: View,
+ ) {
+ when (chipModel) {
+ is OngoingActivityChipModel.Shown.Countdown -> {
+ // Set as assertive so talkback will announce the countdown
+ chipView.accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_ASSERTIVE
+ }
+ is OngoingActivityChipModel.Shown.Timer,
+ is OngoingActivityChipModel.Shown.Text,
+ is OngoingActivityChipModel.Shown.IconOnly -> {
+ chipView.accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_NONE
+ }
+ }
+ // Clickable chips need to be a minimum size for accessibility purposes, but let
+ // non-clickable chips be smaller.
+ if (chipModel.onClickListener != null) {
+ chipBackgroundView.minimumWidth =
+ chipBackgroundView.context.resources.getDimensionPixelSize(
+ R.dimen.min_clickable_item_size
+ )
+ } else {
+ chipBackgroundView.minimumWidth = 0
+ }
+ }
+
+ @IdRes private val CUSTOM_ICON_VIEW_ID = R.id.ongoing_activity_chip_custom_icon
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt
index 04c4516..199eb06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt
@@ -151,13 +151,13 @@
}
/**
- * A flow modeling the chip that should be shown in the status bar after accounting for possibly
- * multiple ongoing activities and animation requirements.
+ * A flow modeling the primary chip that should be shown in the status bar after accounting for
+ * possibly multiple ongoing activities and animation requirements.
*
* [com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment] is responsible for
* actually displaying the chip.
*/
- val chip: StateFlow<OngoingActivityChipModel> =
+ val primaryChip: StateFlow<OngoingActivityChipModel> =
internalChip
.pairwise(initialValue = DEFAULT_INTERNAL_HIDDEN_MODEL)
.map { (old, new) ->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
index 3a2f95e..6d0148a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
@@ -22,7 +22,7 @@
import androidx.annotation.VisibleForTesting;
import com.android.systemui.Dumpable;
-import com.android.systemui.communal.domain.interactor.CommunalInteractor;
+import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dump.DumpManager;
@@ -32,6 +32,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor;
+import com.android.systemui.shade.domain.interactor.ShadeInteractor;
import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.ListEntry;
@@ -43,6 +44,7 @@
import com.android.systemui.statusbar.notification.shared.NotificationMinimalismPrototype;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.concurrency.DelayableExecutor;
+import com.android.systemui.util.kotlin.BooleanFlowOperators;
import com.android.systemui.util.kotlin.JavaAdapter;
import java.io.PrintWriter;
@@ -70,7 +72,8 @@
private final VisibilityLocationProvider mVisibilityLocationProvider;
private final VisualStabilityProvider mVisualStabilityProvider;
private final WakefulnessLifecycle mWakefulnessLifecycle;
- private final CommunalInteractor mCommunalInteractor;
+ private final CommunalSceneInteractor mCommunalSceneInteractor;
+ private final ShadeInteractor mShadeInteractor;
private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
private final VisualStabilityCoordinatorLogger mLogger;
@@ -110,7 +113,8 @@
VisibilityLocationProvider visibilityLocationProvider,
VisualStabilityProvider visualStabilityProvider,
WakefulnessLifecycle wakefulnessLifecycle,
- CommunalInteractor communalInteractor,
+ CommunalSceneInteractor communalSceneInteractor,
+ ShadeInteractor shadeInteractor,
KeyguardTransitionInteractor keyguardTransitionInteractor,
VisualStabilityCoordinatorLogger logger) {
mHeadsUpManager = headsUpManager;
@@ -122,7 +126,8 @@
mWakefulnessLifecycle = wakefulnessLifecycle;
mStatusBarStateController = statusBarStateController;
mDelayableExecutor = delayableExecutor;
- mCommunalInteractor = communalInteractor;
+ mCommunalSceneInteractor = communalSceneInteractor;
+ mShadeInteractor = shadeInteractor;
mKeyguardTransitionInteractor = keyguardTransitionInteractor;
mLogger = logger;
@@ -141,7 +146,11 @@
this::onShadeOrQsClosingChanged);
mJavaAdapter.alwaysCollectFlow(mShadeAnimationInteractor.isLaunchingActivity(),
this::onLaunchingActivityChanged);
- mJavaAdapter.alwaysCollectFlow(mCommunalInteractor.isIdleOnCommunal(),
+ mJavaAdapter.alwaysCollectFlow(
+ BooleanFlowOperators.INSTANCE.allOf(
+ mCommunalSceneInteractor.isIdleOnCommunal(),
+ BooleanFlowOperators.INSTANCE.not(mShadeInteractor.isAnyFullyExpanded())
+ ),
this::onCommunalShowingChanged);
if (SceneContainerFlag.isEnabled()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/NotificationSettingsRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/NotificationSettingsRepositoryModule.kt
index af21e75..d36412c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/NotificationSettingsRepositoryModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/NotificationSettingsRepositoryModule.kt
@@ -16,17 +16,23 @@
package com.android.systemui.statusbar.notification.data
+import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.settings.SecureSettingsRepositoryModule
import com.android.systemui.settings.SystemSettingsRepositoryModule
import com.android.systemui.shared.notifications.data.repository.NotificationSettingsRepository
import com.android.systemui.shared.settings.data.repository.SecureSettingsRepository
import com.android.systemui.shared.settings.data.repository.SystemSettingsRepository
+import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionLogger
import dagger.Module
import dagger.Provides
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
@Module(includes = [SecureSettingsRepositoryModule::class, SystemSettingsRepositoryModule::class])
object NotificationSettingsRepositoryModule {
@@ -42,6 +48,19 @@
backgroundScope,
backgroundDispatcher,
secureSettingsRepository,
- systemSettingsRepository
- )
+ systemSettingsRepository)
+
+ @Provides
+ @IntoMap
+ @ClassKey(NotificationSettingsRepository::class)
+ @SysUISingleton
+ fun provideCoreStartable(
+ @Application applicationScope: CoroutineScope,
+ repository: NotificationSettingsRepository,
+ logger: VisualInterruptionDecisionLogger
+ ) = CoreStartable {
+ applicationScope.launch {
+ repository.isCooldownEnabled.collect { value -> logger.logCooldownSetting(value) }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionLogger.kt
index b83259d..38cab82 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionLogger.kt
@@ -102,6 +102,15 @@
{ "AvalancheSuppressor: $str1" }
)
}
+
+ fun logCooldownSetting(isEnabled: Boolean) {
+ buffer.log(
+ TAG,
+ INFO,
+ { bool1 = isEnabled },
+ { "Cooldown enabled: $bool1" }
+ )
+ }
}
private const val TAG = "VisualInterruptionDecisionProvider"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/Notifications.proto b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/Notifications.proto
index ce4356a..18d4a04 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/Notifications.proto
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/Notifications.proto
@@ -18,7 +18,7 @@
/**
* NotificationList proto from atoms.proto, duplicated here so that it's accessible in the build.
- * Must be kept in sync with the version in atoms.proto.
+ * Must be kept in sync with the version in stats/atoms/sysui/sysui_atoms.proto.
*/
message Notification {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RichOngoingNotificationViewInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RichOngoingNotificationViewInflater.kt
index 2c462b7..77c4130 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RichOngoingNotificationViewInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RichOngoingNotificationViewInflater.kt
@@ -198,12 +198,22 @@
parentView,
/* attachToRoot= */ false
) as EnRouteView
-
InflatedContentViewHolder(newView) {
EnRouteViewBinder.bindWhileAttached(newView, createViewModel())
}
}
- RichOngoingNotificationViewType.Expanded,
+ RichOngoingNotificationViewType.Expanded -> {
+ val newView =
+ LayoutInflater.from(systemUiContext)
+ .inflate(
+ R.layout.notification_template_en_route_expanded,
+ parentView,
+ /* attachToRoot= */ false
+ ) as EnRouteView
+ InflatedContentViewHolder(newView) {
+ EnRouteViewBinder.bindWhileAttached(newView, createViewModel())
+ }
+ }
RichOngoingNotificationViewType.HeadsUp -> NullContentView
}
}
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 b9628e9..8ff1ab6 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
@@ -1389,6 +1389,10 @@
}
private void clampScrollPosition() {
+ // NSSL doesn't control scrolling with SceneContainer enabled
+ if (SceneContainerFlag.isEnabled()) {
+ return;
+ }
int scrollRange = getScrollRange();
if (scrollRange < mOwnScrollY && !mAmbientState.isClearAllInProgress()) {
// if the scroll boundary updates the position of the stack,
@@ -1399,12 +1403,8 @@
}
public int getTopPadding() {
- // TODO(b/332574413) replace all usages of getTopPadding()
- if (SceneContainerFlag.isEnabled()) {
- return (int) mAmbientState.getStackTop();
- } else {
- return mAmbientState.getTopPadding();
- }
+ SceneContainerFlag.assertInLegacyMode();
+ return mAmbientState.getTopPadding();
}
private void onTopPaddingChanged(boolean animate) {
@@ -2446,6 +2446,11 @@
}
private int getScrollRange() {
+ // TODO(b/360091533) Disable the usages of #getScrollRange() with SceneContainer enabled,
+ // because NSSL shouldn't control its own scrolling.
+ if (SceneContainerFlag.isEnabled()) {
+ return 0;
+ }
// In current design, it only use the top HUN to treat all of HUNs
// although there are more than one HUNs
int contentHeight = mContentHeight;
@@ -2881,7 +2886,9 @@
NotificationEntry entry = ((ExpandableNotificationRow) child).getEntry();
entry.removeOnSensitivityChangedListener(mOnChildSensitivityChangedListener);
}
- updateScrollStateForRemovedChild(child);
+ if (!SceneContainerFlag.isEnabled()) {
+ updateScrollStateForRemovedChild(child);
+ }
boolean animationGenerated = container != null && generateRemoveAnimation(child);
if (animationGenerated) {
if (!mSwipedOutViews.contains(child) || !isFullySwipedOut(child)) {
@@ -3060,6 +3067,7 @@
* @param removedChild the removed child
*/
private void updateScrollStateForRemovedChild(ExpandableView removedChild) {
+ SceneContainerFlag.assertInLegacyMode();
final int startingPosition = getPositionInLinearLayout(removedChild);
final int childHeight = getIntrinsicHeight(removedChild) + mPaddingBetweenElements;
final int endPosition = startingPosition + childHeight;
@@ -3081,6 +3089,7 @@
* @return the amount of scrolling needed to start clipping notifications.
*/
private int getScrollAmountToScrollBoundary() {
+ SceneContainerFlag.assertInLegacyMode();
if (mShouldUseSplitNotificationShade) {
return mSidePaddings;
}
@@ -3682,6 +3691,10 @@
if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
switch (event.getAction()) {
case MotionEvent.ACTION_SCROLL: {
+ // If scene container is active, NSSL should not control its own scrolling.
+ if (SceneContainerFlag.isEnabled()) {
+ return false;
+ }
if (!mIsBeingDragged) {
final float vscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
if (vscroll != 0) {
@@ -3710,7 +3723,7 @@
if (!isScrollingEnabled()) {
return false;
}
- if (isInsideQsHeader(ev) && !mIsBeingDragged) {
+ if (!isInScrollableRegion(ev) && !mIsBeingDragged) {
return false;
}
mForcedScroll = null;
@@ -3878,11 +3891,26 @@
return mFlingAfterUpEvent;
}
- protected boolean isInsideQsHeader(MotionEvent ev) {
- if (SceneContainerFlag.isEnabled()) {
- return ev.getY() < mAmbientState.getStackTop();
+ /** Is this touch event inside the scrollable region? */
+ @VisibleForTesting
+ boolean isInScrollableRegion(MotionEvent ev) {
+ if (!SceneContainerFlag.isEnabled()) {
+ return !isInsideQsHeader(ev);
+ }
+ ShadeScrimShape shape = mScrollViewFields.getScrimClippingShape();
+ if (shape == null) {
+ return true; // When there is no scrim, consider this event scrollable.
}
+ ShadeScrimBounds bounds = shape.getBounds();
+ return ev.getX() >= bounds.getLeft()
+ && ev.getX() <= bounds.getRight()
+ && ev.getY() >= bounds.getTop()
+ && ev.getY() <= bounds.getBottom();
+ }
+
+ protected boolean isInsideQsHeader(MotionEvent ev) {
+ SceneContainerFlag.assertInLegacyMode();
if (QSComposeFragment.isEnabled()) {
if (mQSHeaderBoundsProvider == null) {
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
index 580431a..969ff1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
@@ -68,6 +68,7 @@
if (mLabelTextId != null) {
mLabelView.setText(mLabelTextId);
}
+ mLabelView.setAccessibilityHeading(true);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index ef1bcfc..cccac4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -682,7 +682,10 @@
// doesn't get updated quickly enough and can cause the footer to flash when
// closing the shade. As such, we temporarily also check the ambientState directly.
if (((FooterView) view).shouldBeHidden() || !ambientState.isShadeExpanded()) {
- viewState.hidden = true;
+ // Note: This is no longer necessary in flexiglass.
+ if (!SceneContainerFlag.isEnabled()) {
+ viewState.hidden = true;
+ }
} else {
final float footerEnd = algorithmState.mCurrentExpandedYPosition
+ view.getIntrinsicHeight();
@@ -691,7 +694,6 @@
noSpaceForFooter || (ambientState.isClearAllInProgress()
&& !hasNonClearableNotifs(algorithmState));
}
-
} else {
final boolean shadeClosed = !ambientState.isShadeExpanded();
final boolean isShelfShowing = algorithmState.firstViewInShelf != null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt
index d770b20..dc9615c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt
@@ -188,15 +188,26 @@
.startHistoryIntent(view, /* showHistory= */ true)
},
)
- launch {
- viewModel.shouldIncludeFooterView.collect { animatedVisibility ->
- footerView.setVisible(
- /* visible = */ animatedVisibility.value,
- /* animate = */ animatedVisibility.isAnimating,
- )
+ if (SceneContainerFlag.isEnabled) {
+ launch {
+ viewModel.shouldShowFooterView.collect { animatedVisibility ->
+ footerView.setVisible(
+ /* visible = */ animatedVisibility.value,
+ /* animate = */ animatedVisibility.isAnimating,
+ )
+ }
}
+ } else {
+ launch {
+ viewModel.shouldIncludeFooterView.collect { animatedVisibility ->
+ footerView.setVisible(
+ /* visible = */ animatedVisibility.value,
+ /* animate = */ animatedVisibility.isAnimating,
+ )
+ }
+ }
+ launch { viewModel.shouldHideFooterView.collect { footerView.setShouldBeHidden(it) } }
}
- launch { viewModel.shouldHideFooterView.collect { footerView.setShouldBeHidden(it) } }
disposableHandle.awaitCancellationThenDispose()
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt
index e55492e6..4e2a46d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt
@@ -32,6 +32,7 @@
import com.android.systemui.statusbar.policy.domain.interactor.UserSetupInteractor
import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor
import com.android.systemui.util.kotlin.FlowDumperImpl
+import com.android.systemui.util.kotlin.combine
import com.android.systemui.util.kotlin.sample
import com.android.systemui.util.ui.AnimatableEvent
import com.android.systemui.util.ui.AnimatedValue
@@ -120,6 +121,7 @@
* This essentially corresponds to having the view set to INVISIBLE.
*/
val shouldHideFooterView: Flow<Boolean> by lazy {
+ SceneContainerFlag.assertInLegacyMode()
if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
flowOf(false)
} else {
@@ -143,6 +145,7 @@
* be hidden by another condition (see [shouldHideFooterView] above).
*/
val shouldIncludeFooterView: Flow<AnimatedValue<Boolean>> by lazy {
+ SceneContainerFlag.assertInLegacyMode()
if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
flowOf(AnimatedValue.NotAnimating(false))
} else {
@@ -207,6 +210,76 @@
}
}
+ // This flow replaces shouldHideFooterView+shouldIncludeFooterView in flexiglass.
+ val shouldShowFooterView: Flow<AnimatedValue<Boolean>> by lazy {
+ if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) {
+ flowOf(AnimatedValue.NotAnimating(false))
+ } else {
+ combine(
+ activeNotificationsInteractor.areAnyNotificationsPresent,
+ userSetupInteractor.isUserSetUp,
+ notificationStackInteractor.isShowingOnLockscreen,
+ shadeInteractor.isQsFullscreen,
+ remoteInputInteractor.isRemoteInputActive,
+ shadeInteractor.shadeExpansion.map { it < 0.5f }.distinctUntilChanged(),
+ ) {
+ hasNotifications,
+ isUserSetUp,
+ isShowingOnLockscreen,
+ qsFullScreen,
+ isRemoteInputActive,
+ shadeLessThanHalfwayExpanded ->
+ when {
+ !hasNotifications -> VisibilityChange.DISAPPEAR_WITH_ANIMATION
+ // Hide the footer until the user setup is complete, to prevent access
+ // to settings (b/193149550).
+ !isUserSetUp -> VisibilityChange.DISAPPEAR_WITH_ANIMATION
+ // Do not show the footer if the lockscreen is visible (incl. AOD),
+ // except if the shade is opened on top. See also b/219680200.
+ // Do not animate, as that makes the footer appear briefly when
+ // transitioning between the shade and keyguard.
+ isShowingOnLockscreen -> VisibilityChange.DISAPPEAR_WITHOUT_ANIMATION
+ // Do not show the footer if quick settings are fully expanded (except
+ // for the foldable split shade view). See b/201427195 && b/222699879.
+ qsFullScreen -> VisibilityChange.DISAPPEAR_WITH_ANIMATION
+ // Hide the footer if remote input is active (i.e. user is replying to a
+ // notification). See b/75984847.
+ isRemoteInputActive -> VisibilityChange.DISAPPEAR_WITH_ANIMATION
+ // If the shade is not expanded enough, the footer shouldn't be visible.
+ shadeLessThanHalfwayExpanded -> VisibilityChange.DISAPPEAR_WITH_ANIMATION
+ else -> VisibilityChange.APPEAR_WITH_ANIMATION
+ }
+ }
+ .distinctUntilChanged(
+ // Equivalent unless visibility changes
+ areEquivalent = { a: VisibilityChange, b: VisibilityChange ->
+ a.visible == b.visible
+ }
+ )
+ // Should we animate the visibility change?
+ .sample(
+ // TODO(b/322167853): This check is currently duplicated in FooterViewModel,
+ // but instead it should be a field in ShadeAnimationInteractor.
+ combine(
+ shadeInteractor.isShadeFullyExpanded,
+ shadeInteractor.isShadeTouchable,
+ ::Pair
+ )
+ .onStart { emit(Pair(false, false)) }
+ ) { visibilityChange, (isShadeFullyExpanded, animationsEnabled) ->
+ // Animate if the shade is interactive, but NOT on the lockscreen. Having
+ // animations enabled while on the lockscreen makes the footer appear briefly
+ // when transitioning between the shade and keyguard.
+ val shouldAnimate =
+ isShadeFullyExpanded && animationsEnabled && visibilityChange.canAnimate
+ AnimatableEvent(visibilityChange.visible, shouldAnimate)
+ }
+ .toAnimatedValueFlow()
+ .dumpWhileCollecting("shouldShowFooterView")
+ .flowOn(bgDispatcher)
+ }
+ }
+
enum class VisibilityChange(val visible: Boolean, val canAnimate: Boolean) {
DISAPPEAR_WITHOUT_ANIMATION(visible = false, canAnimate = false),
DISAPPEAR_WITH_ANIMATION(visible = false, canAnimate = true),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index c3da7fc..178c318 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -435,13 +435,14 @@
/** Should only be called from {@link KeyguardStatusBarViewController}. */
void onOverlayChanged() {
- int theme = Utils.getThemeAttr(mContext, com.android.internal.R.attr.textAppearanceSmall);
- mCarrierLabel.setTextAppearance(theme);
+ final int carrierTheme = R.style.TextAppearance_StatusBar_Clock;
+ mCarrierLabel.setTextAppearance(carrierTheme);
mBatteryView.updatePercentView();
+ final int userSwitcherTheme = R.style.TextAppearance_StatusBar_UserChip;
TextView userSwitcherName = mUserSwitcherContainer.findViewById(R.id.current_user_name);
if (userSwitcherName != null) {
- userSwitcherName.setTextAppearance(theme);
+ userSwitcherName.setTextAppearance(userSwitcherTheme);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
index 456265b..bef552c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
@@ -78,7 +78,27 @@
private lateinit var battery: BatteryMeterView
private lateinit var clock: Clock
- private lateinit var statusContainer: View
+ private lateinit var startSideContainer: View
+ private lateinit var endSideContainer: View
+
+ private val iconsOnTouchListener =
+ object : View.OnTouchListener {
+ override fun onTouch(v: View, event: MotionEvent): Boolean {
+ // We want to handle only mouse events here to avoid stealing finger touches
+ // from status bar which expands shade when swiped down on. See b/326097469.
+ // We're using onTouchListener instead of onClickListener as the later will lead
+ // to isClickable being set to true and hence ALL touches always being
+ // intercepted. See [View.OnTouchEvent]
+ if (event.source == InputDevice.SOURCE_MOUSE) {
+ if (event.action == MotionEvent.ACTION_UP) {
+ v.performClick()
+ shadeController.animateExpandShade()
+ }
+ return true
+ }
+ return false
+ }
+ }
private val configurationListener =
object : ConfigurationController.ConfigurationListener {
@@ -88,34 +108,10 @@
}
override fun onViewAttached() {
- statusContainer = mView.requireViewById(R.id.system_icons)
clock = mView.requireViewById(R.id.clock)
battery = mView.requireViewById(R.id.battery)
-
addDarkReceivers()
-
- statusContainer.setOnHoverListener(
- statusOverlayHoverListenerFactory.createDarkAwareListener(statusContainer)
- )
- statusContainer.setOnTouchListener(
- object : View.OnTouchListener {
- override fun onTouch(v: View, event: MotionEvent): Boolean {
- // We want to handle only mouse events here to avoid stealing finger touches
- // from status bar which expands shade when swiped down on. See b/326097469.
- // We're using onTouchListener instead of onClickListener as the later will lead
- // to isClickable being set to true and hence ALL touches always being
- // intercepted. See [View.OnTouchEvent]
- if (event.source == InputDevice.SOURCE_MOUSE) {
- if (event.action == MotionEvent.ACTION_UP) {
- v.performClick()
- shadeController.animateExpandShade()
- }
- return true
- }
- return false
- }
- }
- )
+ addCursorSupportToIconContainers()
progressProvider?.setReadyToHandleTransition(true)
configurationController.addCallback(configurationListener)
@@ -146,10 +142,25 @@
}
}
+ private fun addCursorSupportToIconContainers() {
+ endSideContainer = mView.requireViewById(R.id.system_icons)
+ endSideContainer.setOnHoverListener(
+ statusOverlayHoverListenerFactory.createDarkAwareListener(endSideContainer)
+ )
+ endSideContainer.setOnTouchListener(iconsOnTouchListener)
+
+ startSideContainer = mView.requireViewById(R.id.status_bar_start_side_content)
+ startSideContainer.setOnHoverListener(
+ statusOverlayHoverListenerFactory.createDarkAwareListener(startSideContainer)
+ )
+ startSideContainer.setOnTouchListener(iconsOnTouchListener)
+ }
+
@VisibleForTesting
public override fun onViewDetached() {
removeDarkReceivers()
- statusContainer.setOnHoverListener(null)
+ startSideContainer.setOnHoverListener(null)
+ endSideContainer.setOnHoverListener(null)
progressProvider?.setReadyToHandleTransition(false)
moveFromCenterAnimationController?.onViewDetached()
configurationController.removeCallback(configurationListener)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 43f9af6..f3b9371 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -182,6 +182,7 @@
private boolean mBouncerShowingOverDream;
private int mAttemptsToShowBouncer = 0;
private DelayableExecutor mExecutor;
+ private boolean mIsSleeping = false;
private final PrimaryBouncerExpansionCallback mExpansionCallback =
new PrimaryBouncerExpansionCallback() {
@@ -713,7 +714,11 @@
* {@link #needsFullscreenBouncer()}.
*/
protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing, boolean isFalsingReset) {
- if (needsFullscreenBouncer() && !mDozing) {
+ boolean showBouncer = needsFullscreenBouncer() && !mDozing;
+ if (Flags.simPinRaceConditionOnRestart()) {
+ showBouncer = showBouncer && !mIsSleeping;
+ }
+ if (showBouncer) {
// The keyguard might be showing (already). So we need to hide it.
if (!primaryBouncerIsShowing()) {
if (SceneContainerFlag.isEnabled()) {
@@ -992,7 +997,7 @@
} else {
showBouncerOrKeyguard(hideBouncerWhenShowing, isFalsingReset);
}
- if (!SceneContainerFlag.isEnabled() && hideBouncerWhenShowing) {
+ if (!SceneContainerFlag.isEnabled() && hideBouncerWhenShowing && isBouncerShowing()) {
hideAlternateBouncer(true);
mDismissCallbackRegistry.notifyDismissCancelled();
mPrimaryBouncerInteractor.setDismissAction(null, null);
@@ -1041,6 +1046,7 @@
@Override
public void onStartedWakingUp() {
+ mIsSleeping = false;
setRootViewAnimationDisabled(false);
NavigationBarView navBarView = mCentralSurfaces.getNavigationBarView();
if (navBarView != null) {
@@ -1054,6 +1060,7 @@
@Override
public void onStartedGoingToSleep() {
+ mIsSleeping = true;
setRootViewAnimationDisabled(true);
NavigationBarView navBarView = mCentralSurfaces.getNavigationBarView();
if (navBarView != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index 5be4ba2..4a0fdee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -121,7 +121,7 @@
private MultiSourceMinAlphaController mEndSideAlphaController;
private LinearLayout mEndSideContent;
private View mClockView;
- private View mOngoingActivityChip;
+ private View mPrimaryOngoingActivityChip;
private View mNotificationIconAreaInner;
// Visibilities come in from external system callers via disable flags, but we also sometimes
// modify the visibilities internally. We need to store both so that we don't accidentally
@@ -354,7 +354,7 @@
mEndSideContent = mStatusBar.findViewById(R.id.status_bar_end_side_content);
mEndSideAlphaController = new MultiSourceMinAlphaController(mEndSideContent);
mClockView = mStatusBar.findViewById(R.id.clock);
- mOngoingActivityChip = mStatusBar.findViewById(R.id.ongoing_activity_chip);
+ mPrimaryOngoingActivityChip = mStatusBar.findViewById(R.id.ongoing_activity_chip_primary);
showEndSideContent(false);
showClock(false);
initOperatorName();
@@ -636,9 +636,9 @@
// icons so if the icons are disabled then the activity chip should be, too.)
boolean showOngoingActivityChip = hasOngoingActivity && !disableNotifications;
if (showOngoingActivityChip) {
- showOngoingActivityChip(animate);
+ showPrimaryOngoingActivityChip(animate);
} else {
- hideOngoingActivityChip(animate);
+ hidePrimaryOngoingActivityChip(animate);
}
}
@@ -729,20 +729,20 @@
animateShow(mClockView, animate);
}
- /** Hides the ongoing activity chip. */
- private void hideOngoingActivityChip(boolean animate) {
- animateHiddenState(mOngoingActivityChip, View.GONE, animate);
+ /** Hides the primary ongoing activity chip. */
+ private void hidePrimaryOngoingActivityChip(boolean animate) {
+ animateHiddenState(mPrimaryOngoingActivityChip, View.GONE, animate);
}
/**
- * Displays the ongoing activity chip.
+ * Displays the primary ongoing activity chip.
*
* If Flags.statusBarScreenSharingChips is disabled, this chip will only ever contain the
* ongoing call information, If that flag is enabled, it will support different kinds of ongoing
* activities. See b/332662551.
*/
- private void showOngoingActivityChip(boolean animate) {
- animateShow(mOngoingActivityChip, animate);
+ private void showPrimaryOngoingActivityChip(boolean animate) {
+ animateShow(mPrimaryOngoingActivityChip, animate);
}
/**
@@ -850,7 +850,7 @@
private void initOngoingCallChip() {
mOngoingCallController.addCallback(mOngoingCallListener);
- mOngoingCallController.setChipView(mOngoingActivityChip);
+ mOngoingCallController.setChipView(mPrimaryOngoingActivityChip);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt
index 85bbe7e..d601319 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt
@@ -100,7 +100,14 @@
val showSpn = getBooleanExtra(EXTRA_SHOW_SPN, false)
val spn =
if (statusBarSwitchToSpnFromDataSpn()) {
- getStringExtra(EXTRA_SPN)
+ // Context: b/358669494. Use DATA_SPN if it exists, since that allows carriers to
+ // customize the display name. Otherwise, fall back to the SPN
+ val dataSpn = getStringExtra(EXTRA_DATA_SPN)
+ if (dataSpn.isNullOrEmpty()) {
+ getStringExtra(EXTRA_SPN)
+ } else {
+ dataSpn
+ }
} else {
getStringExtra(EXTRA_DATA_SPN)
}
@@ -109,10 +116,8 @@
val plmn = getStringExtra(EXTRA_PLMN)
val str = StringBuilder()
- val strData = StringBuilder()
if (showPlmn && plmn != null) {
str.append(plmn)
- strData.append(plmn)
}
if (showSpn && spn != null) {
if (str.isNotEmpty()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
index c24d694..87d0e64 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
@@ -18,28 +18,16 @@
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
-import android.annotation.IdRes
-import android.content.res.ColorStateList
-import android.graphics.drawable.GradientDrawable
import android.view.View
-import android.view.ViewGroup
-import android.widget.FrameLayout
-import android.widget.ImageView
-import android.widget.TextView
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.Flags
-import com.android.systemui.common.ui.binder.IconViewBinder
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlag
-import com.android.systemui.statusbar.StatusBarIconView
-import com.android.systemui.statusbar.chips.ron.shared.StatusBarRonChips
-import com.android.systemui.statusbar.chips.ui.binder.ChipChronometerBinder
+import com.android.systemui.statusbar.chips.ui.binder.OngoingActivityChipBinder
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
-import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
-import com.android.systemui.statusbar.chips.ui.view.ChipChronometer
import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel
import javax.inject.Inject
@@ -93,58 +81,22 @@
}
if (Flags.statusBarScreenSharingChips()) {
- val chipView: View = view.requireViewById(R.id.ongoing_activity_chip)
- val chipContext = chipView.context
- val chipDefaultIconView: ImageView =
- chipView.requireViewById(R.id.ongoing_activity_chip_icon)
- val chipTimeView: ChipChronometer =
- chipView.requireViewById(R.id.ongoing_activity_chip_time)
- val chipTextView: TextView =
- chipView.requireViewById(R.id.ongoing_activity_chip_text)
- val chipBackgroundView =
- chipView.requireViewById<ChipBackgroundContainer>(
- R.id.ongoing_activity_chip_background
- )
+ val primaryChipView: View =
+ view.requireViewById(R.id.ongoing_activity_chip_primary)
launch {
- viewModel.ongoingActivityChip.collect { chipModel ->
- when (chipModel) {
- is OngoingActivityChipModel.Shown -> {
- // Data
- setChipIcon(chipModel, chipBackgroundView, chipDefaultIconView)
- setChipMainContent(chipModel, chipTextView, chipTimeView)
- chipView.setOnClickListener(chipModel.onClickListener)
- updateChipPadding(
- chipModel,
- chipBackgroundView,
- chipTextView,
- chipTimeView,
- )
-
- // Accessibility
- setChipAccessibility(chipModel, chipView, chipBackgroundView)
-
- // Colors
- val textColor = chipModel.colors.text(chipContext)
- chipTimeView.setTextColor(textColor)
- chipTextView.setTextColor(textColor)
- (chipBackgroundView.background as GradientDrawable).color =
- chipModel.colors.background(chipContext)
-
- // Notify listeners
+ viewModel.primaryOngoingActivityChip.collect { primaryChipModel ->
+ OngoingActivityChipBinder.bind(primaryChipModel, primaryChipView)
+ when (primaryChipModel) {
+ is OngoingActivityChipModel.Shown ->
listener.onOngoingActivityStatusChanged(
hasOngoingActivity = true,
shouldAnimate = true,
)
- }
- is OngoingActivityChipModel.Hidden -> {
- // The Chronometer should be stopped to prevent leaks -- see
- // b/192243808 and [Chronometer.start].
- chipTimeView.stop()
+ is OngoingActivityChipModel.Hidden ->
listener.onOngoingActivityStatusChanged(
hasOngoingActivity = false,
- shouldAnimate = chipModel.shouldAnimate,
+ shouldAnimate = primaryChipModel.shouldAnimate,
)
- }
}
}
}
@@ -161,240 +113,6 @@
}
}
- private fun setChipIcon(
- chipModel: OngoingActivityChipModel.Shown,
- backgroundView: ChipBackgroundContainer,
- defaultIconView: ImageView,
- ) {
- // Always remove any previously set custom icon. If we have a new custom icon, we'll re-add
- // it.
- backgroundView.removeView(backgroundView.getCustomIconView())
-
- val iconTint = chipModel.colors.text(defaultIconView.context)
-
- when (val icon = chipModel.icon) {
- null -> {
- defaultIconView.visibility = View.GONE
- }
- is OngoingActivityChipModel.ChipIcon.SingleColorIcon -> {
- IconViewBinder.bind(icon.impl, defaultIconView)
- defaultIconView.visibility = View.VISIBLE
- defaultIconView.tintView(iconTint)
- }
- is OngoingActivityChipModel.ChipIcon.FullColorAppIcon -> {
- StatusBarRonChips.assertInNewMode()
- IconViewBinder.bind(icon.impl, defaultIconView)
- defaultIconView.visibility = View.VISIBLE
- defaultIconView.untintView()
- }
- is OngoingActivityChipModel.ChipIcon.StatusBarView -> {
- // Hide the default icon since we'll show this custom icon instead.
- defaultIconView.visibility = View.GONE
-
- // Add the new custom icon:
- // 1. Set up the right visual params.
- val iconView = icon.impl
- with(iconView) {
- id = CUSTOM_ICON_VIEW_ID
- // TODO(b/354930838): Update the content description to not include "phone" and
- // maybe include the app name.
- contentDescription =
- context.resources.getString(R.string.ongoing_phone_call_content_description)
- tintView(iconTint)
- }
-
- // 2. If we just reinflated the view, we may need to detach the icon view from the
- // old chip before we reattach it to the new one.
- // See also: NotificationIconContainerViewBinder#bindIcons.
- val currentParent = iconView.parent as? ViewGroup
- if (currentParent != null && currentParent != backgroundView) {
- currentParent.removeView(iconView)
- currentParent.removeTransientView(iconView)
- }
-
- // 3: Add the icon as the starting view.
- backgroundView.addView(
- iconView,
- /* index= */ 0,
- generateCustomIconLayoutParams(iconView),
- )
- }
- }
- }
-
- private fun View.getCustomIconView(): StatusBarIconView? {
- return this.findViewById(CUSTOM_ICON_VIEW_ID)
- }
-
- private fun ImageView.tintView(color: Int) {
- this.imageTintList = ColorStateList.valueOf(color)
- }
-
- private fun ImageView.untintView() {
- this.imageTintList = null
- }
-
- private fun generateCustomIconLayoutParams(iconView: ImageView): FrameLayout.LayoutParams {
- val customIconSize =
- iconView.context.resources.getDimensionPixelSize(
- R.dimen.ongoing_activity_chip_embedded_padding_icon_size
- )
- return FrameLayout.LayoutParams(customIconSize, customIconSize)
- }
-
- private fun setChipMainContent(
- chipModel: OngoingActivityChipModel.Shown,
- chipTextView: TextView,
- chipTimeView: ChipChronometer,
- ) {
- when (chipModel) {
- is OngoingActivityChipModel.Shown.Countdown -> {
- chipTextView.text = chipModel.secondsUntilStarted.toString()
- chipTextView.visibility = View.VISIBLE
-
- chipTimeView.hide()
- }
- is OngoingActivityChipModel.Shown.Text -> {
- chipTextView.text = chipModel.text
- chipTextView.visibility = View.VISIBLE
-
- chipTimeView.hide()
- }
- is OngoingActivityChipModel.Shown.Timer -> {
- ChipChronometerBinder.bind(chipModel.startTimeMs, chipTimeView)
- chipTimeView.visibility = View.VISIBLE
-
- chipTextView.visibility = View.GONE
- }
- is OngoingActivityChipModel.Shown.IconOnly -> {
- chipTextView.visibility = View.GONE
- chipTimeView.hide()
- }
- }
- }
-
- private fun ChipChronometer.hide() {
- // The Chronometer should be stopped to prevent leaks -- see b/192243808 and
- // [Chronometer.start].
- this.stop()
- this.visibility = View.GONE
- }
-
- private fun updateChipPadding(
- chipModel: OngoingActivityChipModel.Shown,
- backgroundView: View,
- chipTextView: TextView,
- chipTimeView: ChipChronometer,
- ) {
- if (chipModel.icon != null) {
- if (chipModel.icon is OngoingActivityChipModel.ChipIcon.StatusBarView) {
- // If the icon is a custom [StatusBarIconView], then it should've come from
- // `Notification.smallIcon`, which is required to embed its own paddings. We need to
- // adjust the other paddings to make everything look good :)
- backgroundView.setBackgroundPaddingForEmbeddedPaddingIcon()
- chipTextView.setTextPaddingForEmbeddedPaddingIcon()
- chipTimeView.setTextPaddingForEmbeddedPaddingIcon()
- } else {
- backgroundView.setBackgroundPaddingForNormalIcon()
- chipTextView.setTextPaddingForNormalIcon()
- chipTimeView.setTextPaddingForNormalIcon()
- }
- } else {
- backgroundView.setBackgroundPaddingForNoIcon()
- chipTextView.setTextPaddingForNoIcon()
- chipTimeView.setTextPaddingForNoIcon()
- }
- }
-
- private fun View.setTextPaddingForEmbeddedPaddingIcon() {
- val newPaddingEnd =
- context.resources.getDimensionPixelSize(
- R.dimen.ongoing_activity_chip_text_end_padding_for_embedded_padding_icon
- )
- setPaddingRelative(
- // The icon should embed enough padding between the icon and time view.
- /* start= */ 0,
- this.paddingTop,
- newPaddingEnd,
- this.paddingBottom,
- )
- }
-
- private fun View.setTextPaddingForNormalIcon() {
- this.setPaddingRelative(
- this.context.resources.getDimensionPixelSize(
- R.dimen.ongoing_activity_chip_icon_text_padding
- ),
- paddingTop,
- // The background view will contain the right end padding.
- /* end= */ 0,
- paddingBottom,
- )
- }
-
- private fun View.setTextPaddingForNoIcon() {
- // The background view will have even start & end paddings, so we don't want the text view
- // to add any additional padding.
- this.setPaddingRelative(/* start= */ 0, paddingTop, /* end= */ 0, paddingBottom)
- }
-
- private fun View.setBackgroundPaddingForEmbeddedPaddingIcon() {
- val sidePadding =
- context.resources.getDimensionPixelSize(
- R.dimen.ongoing_activity_chip_side_padding_for_embedded_padding_icon
- )
- setPaddingRelative(
- sidePadding,
- paddingTop,
- sidePadding,
- paddingBottom,
- )
- }
-
- private fun View.setBackgroundPaddingForNormalIcon() {
- val sidePadding =
- context.resources.getDimensionPixelSize(R.dimen.ongoing_activity_chip_side_padding)
- setPaddingRelative(
- sidePadding,
- paddingTop,
- sidePadding,
- paddingBottom,
- )
- }
-
- private fun View.setBackgroundPaddingForNoIcon() {
- // The padding for the normal icon is also appropriate for no icon.
- setBackgroundPaddingForNormalIcon()
- }
-
- private fun setChipAccessibility(
- chipModel: OngoingActivityChipModel.Shown,
- chipView: View,
- chipBackgroundView: View,
- ) {
- when (chipModel) {
- is OngoingActivityChipModel.Shown.Countdown -> {
- // Set as assertive so talkback will announce the countdown
- chipView.accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_ASSERTIVE
- }
- is OngoingActivityChipModel.Shown.Timer,
- is OngoingActivityChipModel.Shown.Text,
- is OngoingActivityChipModel.Shown.IconOnly -> {
- chipView.accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_NONE
- }
- }
- // Clickable chips need to be a minimum size for accessibility purposes, but let
- // non-clickable chips be smaller.
- if (chipModel.onClickListener != null) {
- chipBackgroundView.minimumWidth =
- chipBackgroundView.context.resources.getDimensionPixelSize(
- R.dimen.min_clickable_item_size
- )
- } else {
- chipBackgroundView.minimumWidth = 0
- }
- }
-
private fun animateLightsOutView(view: View, visible: Boolean) {
view.animate().cancel()
@@ -424,10 +142,6 @@
)
.start()
}
-
- companion object {
- @IdRes private val CUSTOM_ICON_VIEW_ID = R.id.ongoing_activity_chip_custom_icon
- }
}
/** Listener for various events that may affect the status bar's visibility. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt
index d6c3834..5474231 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt
@@ -64,8 +64,11 @@
/** Emits whenever a transition from lockscreen to dream has started. */
val transitionFromLockscreenToDreamStartedEvent: Flow<Unit>
- /** The ongoing activity chip that should be shown on the left-hand side of the status bar. */
- val ongoingActivityChip: StateFlow<OngoingActivityChipModel>
+ /**
+ * The ongoing activity chip that should be primarily shown on the left-hand side of the status
+ * bar. If there are multiple ongoing activity chips, this one should take priority.
+ */
+ val primaryOngoingActivityChip: StateFlow<OngoingActivityChipModel>
/**
* True if the current scene can show the home status bar (aka this status bar), and false if
@@ -108,7 +111,7 @@
.filter { it.transitionState == TransitionState.STARTED }
.map {}
- override val ongoingActivityChip = ongoingActivityChipsViewModel.chip
+ override val primaryOngoingActivityChip = ongoingActivityChipsViewModel.primaryChip
override val isHomeStatusBarAllowedByScene: StateFlow<Boolean> =
combine(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt
index 152d181..7163e67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoWifiRepository.kt
@@ -101,29 +101,20 @@
private fun FakeWifiEventModel.Wifi.toWifiNetworkModel(): WifiNetworkModel =
WifiNetworkModel.Active(
- networkId = DEMO_NET_ID,
isValidated = validated ?: true,
level = level ?: 0,
ssid = ssid ?: DEMO_NET_SSID,
hotspotDeviceType = hotspotDeviceType,
-
- // These fields below aren't supported in demo mode, since they aren't needed to satisfy
- // the interface.
- isPasspointAccessPoint = false,
- isOnlineSignUpForPasspointAccessPoint = false,
- passpointProviderFriendlyName = null,
)
private fun FakeWifiEventModel.CarrierMerged.toCarrierMergedModel(): WifiNetworkModel =
WifiNetworkModel.CarrierMerged(
- networkId = DEMO_NET_ID,
subscriptionId = subscriptionId,
level = level,
numberOfLevels = numberOfLevels,
)
companion object {
- private const val DEMO_NET_ID = 1234
private const val DEMO_NET_SSID = "Demo SSID"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
index 885abca..b6e73e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
@@ -29,8 +29,6 @@
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.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
import com.android.systemui.log.table.TableLogBuffer
@@ -75,7 +73,6 @@
class WifiRepositoryImpl
@Inject
constructor(
- featureFlags: FeatureFlags,
@Application private val scope: CoroutineScope,
@Main private val mainExecutor: Executor,
@Background private val bgDispatcher: CoroutineDispatcher,
@@ -90,8 +87,6 @@
mainExecutor.execute { it.currentState = Lifecycle.State.CREATED }
}
- private val isInstantTetherEnabled = featureFlags.isEnabled(Flags.INSTANT_TETHER)
-
private var wifiPickerTracker: WifiPickerTracker? = null
private val wifiPickerTrackerInfo: StateFlow<WifiPickerTrackerInfo> = run {
@@ -109,16 +104,11 @@
val connectedEntry = wifiPickerTracker.mergedOrPrimaryConnection
logOnWifiEntriesChanged(connectedEntry)
+ val activeNetworks = wifiPickerTracker?.activeWifiEntries ?: emptyList()
val secondaryNetworks =
- if (featureFlags.isEnabled(Flags.WIFI_SECONDARY_NETWORKS)) {
- val activeNetworks =
- wifiPickerTracker?.activeWifiEntries ?: emptyList()
- activeNetworks
- .filter { it != connectedEntry && !it.isPrimaryNetwork }
- .map { it.toWifiNetworkModel() }
- } else {
- emptyList()
- }
+ activeNetworks
+ .filter { it != connectedEntry && !it.isPrimaryNetwork }
+ .map { it.toWifiNetworkModel() }
// [WifiPickerTracker.connectedWifiEntry] will return the same instance
// but with updated internals. For example, when its validation status
@@ -130,7 +120,8 @@
// into our internal model immediately. [toWifiNetworkModel] always
// returns a new instance, so the flow is guaranteed to emit.
send(
- newPrimaryNetwork = connectedEntry?.toPrimaryWifiNetworkModel()
+ newPrimaryNetwork =
+ connectedEntry?.toPrimaryWifiNetworkModel()
?: WIFI_NETWORK_DEFAULT,
newSecondaryNetworks = secondaryNetworks,
newIsDefault = connectedEntry?.isDefaultNetwork ?: false,
@@ -259,7 +250,6 @@
WifiNetworkModel.Invalid(CARRIER_MERGED_INVALID_SUB_ID_REASON)
} else {
WifiNetworkModel.CarrierMerged(
- networkId = NETWORK_ID,
subscriptionId = this.subscriptionId,
level = this.level,
// WifiManager APIs to calculate the signal level start from 0, so
@@ -270,33 +260,34 @@
}
private fun WifiEntry.convertNormalToModel(): WifiNetworkModel {
- if (this.level == WIFI_LEVEL_UNREACHABLE || this.level !in WIFI_LEVEL_MIN..WIFI_LEVEL_MAX) {
+ // WifiEntry instance values aren't guaranteed to be stable between method calls because
+ // WifiPickerTracker is continuously updating the same object. Save the level in a local
+ // variable so that checking the level validity here guarantees that the level will still be
+ // valid when we create the `WifiNetworkModel.Active` instance later. Otherwise, the level
+ // could be valid here but become invalid later, and `WifiNetworkModel.Active` will throw
+ // an exception. See b/362384551.
+ val currentLevel = this.level
+ if (
+ currentLevel == WIFI_LEVEL_UNREACHABLE ||
+ currentLevel !in WIFI_LEVEL_MIN..WIFI_LEVEL_MAX
+ ) {
// If our level means the network is unreachable or the level is otherwise invalid, we
// don't have an active network.
return WifiNetworkModel.Inactive
}
val hotspotDeviceType =
- if (isInstantTetherEnabled && this is HotspotNetworkEntry) {
+ if (this is HotspotNetworkEntry) {
this.deviceType.toHotspotDeviceType()
} else {
WifiNetworkModel.HotspotDeviceType.NONE
}
return WifiNetworkModel.Active(
- networkId = NETWORK_ID,
isValidated = this.hasInternetAccess(),
- level = this.level,
+ level = currentLevel,
ssid = this.title,
hotspotDeviceType = hotspotDeviceType,
- // With WifiTrackerLib, [WifiEntry.title] will appropriately fetch the SSID for
- // typical wifi networks *and* passpoint/OSU APs. So, the AP-specific values can
- // always be false/null in this repository.
- // TODO(b/292534484): Remove these fields from the wifi network model once this
- // repository is fully enabled.
- isPasspointAccessPoint = false,
- isOnlineSignUpForPasspointAccessPoint = false,
- passpointProviderFriendlyName = null,
)
}
@@ -408,7 +399,6 @@
class Factory
@Inject
constructor(
- private val featureFlags: FeatureFlags,
@Application private val scope: CoroutineScope,
@Main private val mainExecutor: Executor,
@Background private val bgDispatcher: CoroutineDispatcher,
@@ -418,7 +408,6 @@
) {
fun create(wifiManager: WifiManager): WifiRepositoryImpl {
return WifiRepositoryImpl(
- featureFlags,
scope,
mainExecutor,
bgDispatcher,
@@ -439,19 +428,5 @@
val ACTIVITY_DEFAULT = DataActivityModel(hasActivityIn = false, hasActivityOut = false)
private const val TAG = "WifiTrackerLibInputLog"
-
- /**
- * [WifiNetworkModel.Active.networkId] is only used at the repository layer. It's used by
- * [WifiRepositoryImpl], which tracks the ID in order to correctly apply the framework
- * callbacks within the repository.
- *
- * Since this class does not need to manually apply framework callbacks and since the
- * network ID is not used beyond the repository, it's safe to use an invalid ID in this
- * repository.
- *
- * The [WifiNetworkModel.Active.networkId] field should be deleted once we've fully migrated
- * to [WifiRepositoryImpl].
- */
- private const val NETWORK_ID = -1
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt
index 110e339..c0b0c4a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt
@@ -83,8 +83,6 @@
is WifiNetworkModel.CarrierMerged -> null
is WifiNetworkModel.Active ->
when {
- info.isPasspointAccessPoint || info.isOnlineSignUpForPasspointAccessPoint ->
- info.passpointProviderFriendlyName
info.hasValidSsid() -> info.ssid
else -> null
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt
index 7078a2e..39842fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt
@@ -24,6 +24,7 @@
import com.android.systemui.log.table.TableRowLogger
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
import com.android.wifitrackerlib.HotspotNetworkEntry.DeviceType
+import com.android.wifitrackerlib.WifiEntry
/** Provides information about the current wifi network. */
sealed class WifiNetworkModel : Diffable<WifiNetworkModel> {
@@ -38,6 +39,7 @@
*/
object Unavailable : WifiNetworkModel() {
override fun toString() = "WifiNetwork.Unavailable"
+
override fun logDiffs(prevVal: WifiNetworkModel, row: TableRowLogger) {
if (prevVal is Unavailable) {
return
@@ -48,16 +50,12 @@
override fun logFull(row: TableRowLogger) {
row.logChange(COL_NETWORK_TYPE, TYPE_UNAVAILABLE)
- row.logChange(COL_NETWORK_ID, NETWORK_ID_DEFAULT)
row.logChange(COL_SUB_ID, SUB_ID_DEFAULT)
row.logChange(COL_VALIDATED, false)
row.logChange(COL_LEVEL, LEVEL_DEFAULT)
row.logChange(COL_NUM_LEVELS, NUM_LEVELS_DEFAULT)
row.logChange(COL_SSID, null)
row.logChange(COL_HOTSPOT, null)
- row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
- row.logChange(COL_ONLINE_SIGN_UP, false)
- row.logChange(COL_PASSPOINT_NAME, null)
}
}
@@ -67,6 +65,7 @@
val invalidReason: String,
) : WifiNetworkModel() {
override fun toString() = "WifiNetwork.Invalid[$invalidReason]"
+
override fun logDiffs(prevVal: WifiNetworkModel, row: TableRowLogger) {
if (prevVal !is Invalid) {
logFull(row)
@@ -80,16 +79,12 @@
override fun logFull(row: TableRowLogger) {
row.logChange(COL_NETWORK_TYPE, "$TYPE_UNAVAILABLE $invalidReason")
- row.logChange(COL_NETWORK_ID, NETWORK_ID_DEFAULT)
row.logChange(COL_SUB_ID, SUB_ID_DEFAULT)
row.logChange(COL_VALIDATED, false)
row.logChange(COL_LEVEL, LEVEL_DEFAULT)
row.logChange(COL_NUM_LEVELS, NUM_LEVELS_DEFAULT)
row.logChange(COL_SSID, null)
row.logChange(COL_HOTSPOT, null)
- row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
- row.logChange(COL_ONLINE_SIGN_UP, false)
- row.logChange(COL_PASSPOINT_NAME, null)
}
}
@@ -108,16 +103,12 @@
override fun logFull(row: TableRowLogger) {
row.logChange(COL_NETWORK_TYPE, TYPE_INACTIVE)
- row.logChange(COL_NETWORK_ID, NETWORK_ID_DEFAULT)
row.logChange(COL_SUB_ID, SUB_ID_DEFAULT)
row.logChange(COL_VALIDATED, false)
row.logChange(COL_LEVEL, LEVEL_DEFAULT)
row.logChange(COL_NUM_LEVELS, NUM_LEVELS_DEFAULT)
row.logChange(COL_SSID, null)
row.logChange(COL_HOTSPOT, null)
- row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
- row.logChange(COL_ONLINE_SIGN_UP, false)
- row.logChange(COL_PASSPOINT_NAME, null)
}
}
@@ -129,14 +120,6 @@
*/
data class CarrierMerged(
/**
- * The [android.net.Network.netId] we received from
- * [android.net.ConnectivityManager.NetworkCallback] in association with this wifi network.
- *
- * Importantly, **not** [android.net.wifi.WifiInfo.getNetworkId].
- */
- val networkId: Int,
-
- /**
* The subscription ID that this connection represents.
*
* Comes from [android.net.wifi.WifiInfo.getSubscriptionId].
@@ -154,7 +137,8 @@
) : WifiNetworkModel() {
init {
require(level in MIN_VALID_LEVEL..numberOfLevels) {
- "0 <= wifi level <= $numberOfLevels required; level was $level"
+ "CarrierMerged: $MIN_VALID_LEVEL <= wifi level <= $numberOfLevels required; " +
+ "level was $level"
}
require(subscriptionId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
"subscription ID cannot be invalid"
@@ -167,9 +151,6 @@
return
}
- if (prevVal.networkId != networkId) {
- row.logChange(COL_NETWORK_ID, networkId)
- }
if (prevVal.subscriptionId != subscriptionId) {
row.logChange(COL_SUB_ID, subscriptionId)
}
@@ -183,29 +164,17 @@
override fun logFull(row: TableRowLogger) {
row.logChange(COL_NETWORK_TYPE, TYPE_CARRIER_MERGED)
- row.logChange(COL_NETWORK_ID, networkId)
row.logChange(COL_SUB_ID, subscriptionId)
row.logChange(COL_VALIDATED, true)
row.logChange(COL_LEVEL, level)
row.logChange(COL_NUM_LEVELS, numberOfLevels)
row.logChange(COL_SSID, null)
row.logChange(COL_HOTSPOT, null)
- row.logChange(COL_PASSPOINT_ACCESS_POINT, false)
- row.logChange(COL_ONLINE_SIGN_UP, false)
- row.logChange(COL_PASSPOINT_NAME, null)
}
}
/** Provides information about an active wifi network. */
data class Active(
- /**
- * The [android.net.Network.netId] we received from
- * [android.net.ConnectivityManager.NetworkCallback] in association with this wifi network.
- *
- * Importantly, **not** [android.net.wifi.WifiInfo.getNetworkId].
- */
- val networkId: Int,
-
/** See [android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED]. */
val isValidated: Boolean = false,
@@ -220,19 +189,11 @@
* isn't a hotspot connection.
*/
val hotspotDeviceType: HotspotDeviceType = WifiNetworkModel.HotspotDeviceType.NONE,
-
- /** See [android.net.wifi.WifiInfo.isPasspointAp]. */
- val isPasspointAccessPoint: Boolean = false,
-
- /** See [android.net.wifi.WifiInfo.isOsuAp]. */
- val isOnlineSignUpForPasspointAccessPoint: Boolean = false,
-
- /** See [android.net.wifi.WifiInfo.passpointProviderFriendlyName]. */
- val passpointProviderFriendlyName: String? = null,
) : WifiNetworkModel() {
init {
require(level in MIN_VALID_LEVEL..MAX_VALID_LEVEL) {
- "0 <= wifi level <= 4 required; level was $level"
+ "Active: $MIN_VALID_LEVEL <= wifi level <= $MAX_VALID_LEVEL required; " +
+ "level was $level"
}
}
@@ -247,9 +208,6 @@
return
}
- if (prevVal.networkId != networkId) {
- row.logChange(COL_NETWORK_ID, networkId)
- }
if (prevVal.isValidated != isValidated) {
row.logChange(COL_VALIDATED, isValidated)
}
@@ -262,68 +220,25 @@
if (prevVal.hotspotDeviceType != hotspotDeviceType) {
row.logChange(COL_HOTSPOT, hotspotDeviceType.name)
}
-
- // TODO(b/238425913): The passpoint-related values are frequently never used, so it
- // would be great to not log them when they're not used.
- if (prevVal.isPasspointAccessPoint != isPasspointAccessPoint) {
- row.logChange(COL_PASSPOINT_ACCESS_POINT, isPasspointAccessPoint)
- }
- if (
- prevVal.isOnlineSignUpForPasspointAccessPoint !=
- isOnlineSignUpForPasspointAccessPoint
- ) {
- row.logChange(COL_ONLINE_SIGN_UP, isOnlineSignUpForPasspointAccessPoint)
- }
- if (prevVal.passpointProviderFriendlyName != passpointProviderFriendlyName) {
- row.logChange(COL_PASSPOINT_NAME, passpointProviderFriendlyName)
- }
}
override fun logFull(row: TableRowLogger) {
row.logChange(COL_NETWORK_TYPE, TYPE_ACTIVE)
- row.logChange(COL_NETWORK_ID, networkId)
row.logChange(COL_SUB_ID, null)
row.logChange(COL_VALIDATED, isValidated)
row.logChange(COL_LEVEL, level)
row.logChange(COL_NUM_LEVELS, null)
row.logChange(COL_SSID, ssid)
row.logChange(COL_HOTSPOT, hotspotDeviceType.name)
- row.logChange(COL_PASSPOINT_ACCESS_POINT, isPasspointAccessPoint)
- row.logChange(COL_ONLINE_SIGN_UP, isOnlineSignUpForPasspointAccessPoint)
- row.logChange(COL_PASSPOINT_NAME, passpointProviderFriendlyName)
- }
-
- override fun toString(): String {
- // Only include the passpoint-related values in the string if we have them. (Most
- // networks won't have them so they'll be mostly clutter.)
- val passpointString =
- if (
- isPasspointAccessPoint ||
- isOnlineSignUpForPasspointAccessPoint ||
- passpointProviderFriendlyName != null
- ) {
- ", isPasspointAp=$isPasspointAccessPoint, " +
- "isOnlineSignUpForPasspointAp=$isOnlineSignUpForPasspointAccessPoint, " +
- "passpointName=$passpointProviderFriendlyName"
- } else {
- ""
- }
-
- return "WifiNetworkModel.Active(networkId=$networkId, isValidated=$isValidated, " +
- "level=$level, ssid=$ssid$passpointString)"
}
companion object {
- // TODO(b/292534484): Use [com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MAX] instead
- // once the migration to WifiTrackerLib is complete.
- @VisibleForTesting internal const val MAX_VALID_LEVEL = 4
+ @VisibleForTesting internal const val MAX_VALID_LEVEL = WifiEntry.WIFI_LEVEL_MAX
}
}
companion object {
- // TODO(b/292534484): Use [com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MIN] instead
- // once the migration to WifiTrackerLib is complete.
- @VisibleForTesting internal const val MIN_VALID_LEVEL = 0
+ @VisibleForTesting internal const val MIN_VALID_LEVEL = WifiEntry.WIFI_LEVEL_MIN
}
/**
@@ -367,18 +282,13 @@
const val TYPE_ACTIVE = "Active"
const val COL_NETWORK_TYPE = "type"
-const val COL_NETWORK_ID = "networkId"
const val COL_SUB_ID = "subscriptionId"
const val COL_VALIDATED = "isValidated"
const val COL_LEVEL = "level"
const val COL_NUM_LEVELS = "maxLevel"
const val COL_SSID = "ssid"
const val COL_HOTSPOT = "hotspot"
-const val COL_PASSPOINT_ACCESS_POINT = "isPasspointAccessPoint"
-const val COL_ONLINE_SIGN_UP = "isOnlineSignUpForPasspointAccessPoint"
-const val COL_PASSPOINT_NAME = "passpointProviderFriendlyName"
val LEVEL_DEFAULT: String? = null
val NUM_LEVELS_DEFAULT: String? = null
-val NETWORK_ID_DEFAULT: String? = null
val SUB_ID_DEFAULT: String? = null
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt
index 0e88f44..af93880 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt
@@ -90,9 +90,11 @@
viewModel.subtext,
fontWeight = FontWeight.W400,
modifier =
- Modifier.tileMarquee().testTag("state").clearAndSetSemantics {
- contentDescription = viewModel.subtextDescription
- }
+ Modifier.tileMarquee()
+ .testTag(if (viewModel.enabled) "stateOn" else "stateOff")
+ .clearAndSetSemantics {
+ contentDescription = viewModel.subtextDescription
+ }
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/telephony/domain/interactor/TelephonyInteractor.kt b/packages/SystemUI/src/com/android/systemui/telephony/domain/interactor/TelephonyInteractor.kt
index 4b0e5d1..6d99183 100644
--- a/packages/SystemUI/src/com/android/systemui/telephony/domain/interactor/TelephonyInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/telephony/domain/interactor/TelephonyInteractor.kt
@@ -29,11 +29,12 @@
class TelephonyInteractor
@Inject
constructor(
- repository: TelephonyRepository,
+ private val repository: TelephonyRepository,
) {
@Annotation.CallState val callState: Flow<Int> = repository.callState
val isInCall: StateFlow<Boolean> = repository.isInCall
- val hasTelephonyRadio: Boolean = repository.hasTelephonyRadio
+ val hasTelephonyRadio: Boolean
+ get() = repository.hasTelephonyRadio
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index 28effe9..d9e72bf 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -1280,6 +1280,8 @@
private final class Receiver extends BroadcastReceiver {
+ private static final int STREAM_UNKNOWN = -1;
+
public void init() {
final IntentFilter filter = new IntentFilter();
filter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
@@ -1301,30 +1303,38 @@
final String action = intent.getAction();
boolean changed = false;
if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {
- final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
- final int level = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1);
+ final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
+ STREAM_UNKNOWN);
final int oldLevel = intent
.getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, -1);
if (D.BUG) Log.d(TAG, "onReceive VOLUME_CHANGED_ACTION stream=" + stream
- + " level=" + level + " oldLevel=" + oldLevel);
- changed = updateStreamLevelW(stream, level);
+ + " oldLevel=" + oldLevel);
+ if (stream != STREAM_UNKNOWN) {
+ changed |= onVolumeChangedW(stream, 0);
+ }
} else if (action.equals(AudioManager.STREAM_DEVICES_CHANGED_ACTION)) {
- final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+ final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
+ STREAM_UNKNOWN);
final int devices = intent
.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, -1);
final int oldDevices = intent
.getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, -1);
if (D.BUG) Log.d(TAG, "onReceive STREAM_DEVICES_CHANGED_ACTION stream="
+ stream + " devices=" + devices + " oldDevices=" + oldDevices);
- changed = checkRoutedToBluetoothW(stream);
- changed |= onVolumeChangedW(stream, 0);
+ if (stream != STREAM_UNKNOWN) {
+ changed |= checkRoutedToBluetoothW(stream);
+ changed |= onVolumeChangedW(stream, 0);
+ }
} else if (action.equals(AudioManager.STREAM_MUTE_CHANGED_ACTION)) {
- final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+ final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
+ STREAM_UNKNOWN);
final boolean muted = intent
.getBooleanExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, false);
if (D.BUG) Log.d(TAG, "onReceive STREAM_MUTE_CHANGED_ACTION stream=" + stream
+ " muted=" + muted);
- changed = updateStreamMuteW(stream, muted);
+ if (stream != STREAM_UNKNOWN) {
+ changed = updateStreamMuteW(stream, muted);
+ }
} else if (action.equals(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED)) {
if (D.BUG) Log.d(TAG, "onReceive ACTION_EFFECTS_SUPPRESSOR_CHANGED");
changed = updateEffectsSuppressorW(mNoMan.getEffectsSuppressor());
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/CaptioningModule.kt b/packages/SystemUI/src/com/android/systemui/volume/dagger/CaptioningModule.kt
index 73f5237..28a43df 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dagger/CaptioningModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/CaptioningModule.kt
@@ -16,35 +16,16 @@
package com.android.systemui.volume.dagger
-import android.view.accessibility.CaptioningManager
-import com.android.settingslib.view.accessibility.data.repository.CaptioningRepository
-import com.android.settingslib.view.accessibility.data.repository.CaptioningRepositoryImpl
-import com.android.settingslib.view.accessibility.domain.interactor.CaptioningInteractor
+import com.android.systemui.accessibility.data.repository.CaptioningRepository
+import com.android.systemui.accessibility.data.repository.CaptioningRepositoryImpl
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Background
+import dagger.Binds
import dagger.Module
-import dagger.Provides
-import kotlin.coroutines.CoroutineContext
-import kotlinx.coroutines.CoroutineScope
@Module
interface CaptioningModule {
- companion object {
-
- @Provides
- @SysUISingleton
- fun provideCaptioningRepository(
- captioningManager: CaptioningManager,
- @Background coroutineContext: CoroutineContext,
- @Application coroutineScope: CoroutineScope,
- ): CaptioningRepository =
- CaptioningRepositoryImpl(captioningManager, coroutineContext, coroutineScope)
-
- @Provides
- @SysUISingleton
- fun provideCaptioningInteractor(repository: CaptioningRepository): CaptioningInteractor =
- CaptioningInteractor(repository)
- }
+ @Binds
+ @SysUISingleton
+ fun bindCaptioningRepository(impl: CaptioningRepositoryImpl): CaptioningRepository
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt
index 85da1d0..2e5e389 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt
@@ -17,7 +17,7 @@
package com.android.systemui.volume.panel.component.captioning.domain
import com.android.internal.logging.UiEventLogger
-import com.android.settingslib.view.accessibility.domain.interactor.CaptioningInteractor
+import com.android.systemui.accessibility.domain.interactor.CaptioningInteractor
import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
import com.android.systemui.volume.panel.domain.ComponentAvailabilityCriteria
import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
@@ -26,7 +26,7 @@
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.flow.shareIn
+import kotlinx.coroutines.flow.stateIn
@VolumePanelScope
class CaptioningAvailabilityCriteria
@@ -45,7 +45,7 @@
else VolumePanelUiEvent.VOLUME_PANEL_LIVE_CAPTION_TOGGLE_GONE
)
}
- .shareIn(scope, SharingStarted.WhileSubscribed(), replay = 1)
+ .stateIn(scope, SharingStarted.WhileSubscribed(), false)
override fun isAvailable(): Flow<Boolean> = availability
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModel.kt
index ca5aef8..9e70843 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModel.kt
@@ -18,7 +18,7 @@
import android.content.Context
import com.android.internal.logging.UiEventLogger
-import com.android.settingslib.view.accessibility.domain.interactor.CaptioningInteractor
+import com.android.systemui.accessibility.domain.interactor.CaptioningInteractor
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.res.R
import com.android.systemui.volume.panel.component.button.ui.viewmodel.ButtonViewModel
diff --git a/packages/SystemUI/tests/Android.bp b/packages/SystemUI/tests/Android.bp
index 88939a2..f601387 100644
--- a/packages/SystemUI/tests/Android.bp
+++ b/packages/SystemUI/tests/Android.bp
@@ -50,3 +50,14 @@
additional_manifests: ["AndroidManifest.xml"],
manifest: "AndroidManifest-base.xml",
}
+
+test_module_config {
+ name: "SystemUITests_systemui_accessibility",
+ base: "SystemUITests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.systemui.accessibility"],
+ exclude_annotations: [
+ "android.platform.test.annotations.Postsubmit",
+ "android.platform.test.annotations.FlakyTest",
+ ],
+}
diff --git a/packages/SystemUI/tests/goldens/bouncerPredictiveBackMotion.json b/packages/SystemUI/tests/goldens/bouncerPredictiveBackMotion.json
new file mode 100644
index 0000000..f37580d
--- /dev/null
+++ b/packages/SystemUI/tests/goldens/bouncerPredictiveBackMotion.json
@@ -0,0 +1,831 @@
+{
+ "frame_ids": [
+ "before",
+ 0,
+ 16,
+ 32,
+ 48,
+ 64,
+ 80,
+ 96,
+ 112,
+ 128,
+ 144,
+ 160,
+ 176,
+ 192,
+ 208,
+ 224,
+ 240,
+ 256,
+ 272,
+ 288,
+ 304,
+ 320,
+ 336,
+ 352,
+ 368,
+ 384,
+ 400,
+ 416,
+ 432,
+ 448,
+ 464,
+ 480,
+ 496,
+ 512,
+ 528,
+ 544,
+ 560,
+ 576,
+ 592,
+ 608,
+ 624,
+ 640,
+ 656,
+ 672,
+ 688,
+ 704,
+ 720,
+ 736,
+ 752,
+ 768,
+ 784,
+ 800,
+ 816,
+ 832,
+ 848,
+ 864,
+ 880,
+ 896,
+ 912,
+ 928,
+ 944,
+ 960,
+ 976,
+ 992,
+ 1008,
+ 1024,
+ "after"
+ ],
+ "features": [
+ {
+ "name": "content_alpha",
+ "type": "float",
+ "data_points": [
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 0.9954499,
+ 0.9805035,
+ 0.9527822,
+ 0.9092045,
+ 0.84588075,
+ 0.7583043,
+ 0.6424476,
+ 0.49766344,
+ 0.33080608,
+ 0.15650165,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ {
+ "type": "not_found"
+ }
+ ]
+ },
+ {
+ "name": "content_scale",
+ "type": "scale",
+ "data_points": [
+ "default",
+ {
+ "x": 0.9995097,
+ "y": 0.9995097,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.997352,
+ "y": 0.997352,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.990635,
+ "y": 0.990635,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.97249764,
+ "y": 0.97249764,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.94287145,
+ "y": 0.94287145,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.9128026,
+ "y": 0.9128026,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8859569,
+ "y": 0.8859569,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8629254,
+ "y": 0.8629254,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8442908,
+ "y": 0.8442908,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8303209,
+ "y": 0.8303209,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8205137,
+ "y": 0.8205137,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.81387186,
+ "y": 0.81387186,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.80941653,
+ "y": 0.80941653,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.80641484,
+ "y": 0.80641484,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.80437464,
+ "y": 0.80437464,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.80297637,
+ "y": 0.80297637,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.80201286,
+ "y": 0.80201286,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8013477,
+ "y": 0.8013477,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8008894,
+ "y": 0.8008894,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8005756,
+ "y": 0.8005756,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.80036324,
+ "y": 0.80036324,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8002219,
+ "y": 0.8002219,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.80012995,
+ "y": 0.80012995,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8000721,
+ "y": 0.8000721,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.80003715,
+ "y": 0.80003715,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8000173,
+ "y": 0.8000173,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.800007,
+ "y": 0.800007,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8000022,
+ "y": 0.8000022,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8000004,
+ "y": 0.8000004,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.79999995,
+ "y": 0.79999995,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "x": 0.8,
+ "y": 0.8,
+ "pivot": "unspecified"
+ },
+ {
+ "type": "not_found"
+ }
+ ]
+ },
+ {
+ "name": "content_offset",
+ "type": "dpOffset",
+ "data_points": [
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "x": 0,
+ "y": 0.5714286
+ },
+ {
+ "x": 0,
+ "y": 2.857143
+ },
+ {
+ "x": 0,
+ "y": 7.142857
+ },
+ {
+ "x": 0,
+ "y": 13.714286
+ },
+ {
+ "x": 0,
+ "y": 23.142857
+ },
+ {
+ "x": 0,
+ "y": 36.285713
+ },
+ {
+ "x": 0,
+ "y": 53.714287
+ },
+ {
+ "x": 0,
+ "y": 75.42857
+ },
+ {
+ "x": 0,
+ "y": 100.28571
+ },
+ {
+ "x": 0,
+ "y": 126.57143
+ },
+ {
+ "x": 0,
+ "y": 151.42857
+ },
+ {
+ "x": 0,
+ "y": 174
+ },
+ {
+ "x": 0,
+ "y": 193.42857
+ },
+ {
+ "x": 0,
+ "y": 210.28572
+ },
+ {
+ "x": 0,
+ "y": 224.85715
+ },
+ {
+ "x": 0,
+ "y": 237.14285
+ },
+ {
+ "x": 0,
+ "y": 247.71428
+ },
+ {
+ "x": 0,
+ "y": 256.85715
+ },
+ {
+ "x": 0,
+ "y": 264.57144
+ },
+ {
+ "x": 0,
+ "y": 271.42856
+ },
+ {
+ "x": 0,
+ "y": 277.14285
+ },
+ {
+ "x": 0,
+ "y": 282
+ },
+ {
+ "x": 0,
+ "y": 286.2857
+ },
+ {
+ "x": 0,
+ "y": 289.7143
+ },
+ {
+ "x": 0,
+ "y": 292.57144
+ },
+ {
+ "x": 0,
+ "y": 294.85715
+ },
+ {
+ "x": 0,
+ "y": 296.85715
+ },
+ {
+ "x": 0,
+ "y": 298.2857
+ },
+ {
+ "x": 0,
+ "y": 299.14285
+ },
+ {
+ "x": 0,
+ "y": 299.7143
+ },
+ {
+ "x": 0,
+ "y": 300
+ },
+ {
+ "x": 0,
+ "y": 0
+ },
+ {
+ "type": "not_found"
+ }
+ ]
+ },
+ {
+ "name": "background_alpha",
+ "type": "float",
+ "data_points": [
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 0.9900334,
+ 0.8403853,
+ 0.71002257,
+ 0.5979084,
+ 0.50182605,
+ 0.41945767,
+ 0.34874845,
+ 0.28797746,
+ 0.23573697,
+ 0.19087732,
+ 0.1524564,
+ 0.11970067,
+ 0.091962695,
+ 0.068702936,
+ 0.049464583,
+ 0.033859253,
+ 0.021552086,
+ 0.012255073,
+ 0.005717635,
+ 0.0017191172,
+ 6.711483e-05,
+ 0,
+ {
+ "type": "not_found"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
index a8ab922..d85b774 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
@@ -446,14 +446,10 @@
assertFalse(mWifiRepository.isWifiConnectedWithValidSsid());
mWifiRepository.setWifiNetwork(
new WifiNetworkModel.Active(
- /* networkId= */ 0,
/* isValidated= */ false,
/* level= */ 0,
/* ssid= */ "",
- /* hotspotDeviceType= */ WifiNetworkModel.HotspotDeviceType.NONE,
- /* isPasspointAccessPoint= */ false,
- /* isOnlineSignUpForPasspointAccessPoint= */ false,
- /* passpointProviderFriendlyName= */ null));
+ /* hotspotDeviceType= */ WifiNetworkModel.HotspotDeviceType.NONE));
assertTrue(mWifiRepository.isWifiConnectedWithValidSsid());
mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
index 347605d..c42e25b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
@@ -19,6 +19,7 @@
import android.app.ActivityTaskManager
import android.content.pm.PackageManager
import android.os.PowerManager
+import android.platform.test.annotations.EnableFlags
import android.telecom.TelecomManager
import android.telephony.TelephonyManager
import android.testing.TestableLooper
@@ -26,14 +27,20 @@
import androidx.test.filters.SmallTest
import com.android.internal.logging.MetricsLogger
import com.android.internal.widget.LockPatternUtils
+import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
+import com.android.systemui.haptics.msdl.fakeMSDLPlayer
+import com.android.systemui.haptics.msdl.msdlPlayer
import com.android.systemui.shade.ShadeController
import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.testKosmos
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
+import com.google.android.msdl.data.model.MSDLToken
+import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -64,6 +71,8 @@
val fakeSystemClock = FakeSystemClock()
val mainExecutor = FakeExecutor(fakeSystemClock)
val backgroundExecutor = FakeExecutor(fakeSystemClock)
+ private val kosmos = testKosmos()
+ private val msdlPlayer = kosmos.fakeMSDLPlayer
lateinit var underTest: EmergencyButtonController
@@ -84,6 +93,7 @@
mainExecutor,
backgroundExecutor,
mSelectedUserInteractor,
+ msdlPlayer,
)
context.setMockPackageManager(packageManager)
Mockito.`when`(emergencyButton.context).thenReturn(context)
@@ -113,4 +123,13 @@
/* isSecure= */ eq(true)
)
}
+
+ @Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun takeEmergencyCallAction_withMSDLFeedback_playsEmergencyButtonTokenAndNullAttributes() {
+ underTest.takeEmergencyCallAction()
+
+ assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.KEYPRESS_RETURN)
+ assertThat(msdlPlayer.latestPropertiesPlayed).isNull()
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java
index d3b7d22..662815e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java
@@ -52,7 +52,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import com.android.internal.logging.UiEventLogger;
import com.android.settingslib.bluetooth.BluetoothEventManager;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
@@ -92,6 +91,7 @@
@Rule
public MockitoRule mockito = MockitoJUnit.rule();
+ private static final int TEST_LAUNCH_SOURCE_ID = 1;
private static final String DEVICE_ADDRESS = "AA:BB:CC:DD:EE:FF";
private static final String DEVICE_NAME = "test_name";
private static final String TEST_PKG = "pkg";
@@ -124,7 +124,7 @@
@Mock
private AudioManager mAudioManager;
@Mock
- private UiEventLogger mUiEventLogger;
+ private HearingDevicesUiEventLogger mUiEventLogger;
@Mock
private CachedBluetoothDevice mCachedDevice;
@Mock
@@ -182,7 +182,8 @@
anyInt(), any());
assertThat(intentCaptor.getValue().getAction()).isEqualTo(
Settings.ACTION_HEARING_DEVICE_PAIRING_SETTINGS);
- verify(mUiEventLogger).log(HearingDevicesUiEvent.HEARING_DEVICES_PAIR);
+ verify(mUiEventLogger).log(HearingDevicesUiEvent.HEARING_DEVICES_PAIR,
+ TEST_LAUNCH_SOURCE_ID);
}
@Test
@@ -196,7 +197,8 @@
anyInt(), any());
assertThat(intentCaptor.getValue().getAction()).isEqualTo(
HearingDevicesDialogDelegate.ACTION_BLUETOOTH_DEVICE_DETAILS);
- verify(mUiEventLogger).log(HearingDevicesUiEvent.HEARING_DEVICES_GEAR_CLICK);
+ verify(mUiEventLogger).log(HearingDevicesUiEvent.HEARING_DEVICES_GEAR_CLICK,
+ TEST_LAUNCH_SOURCE_ID);
}
@Test
@@ -207,7 +209,8 @@
mDialogDelegate.onDeviceItemClicked(mHearingDeviceItem, new View(mContext));
verify(mCachedDevice).disconnect();
- verify(mUiEventLogger).log(HearingDevicesUiEvent.HEARING_DEVICES_DISCONNECT);
+ verify(mUiEventLogger).log(HearingDevicesUiEvent.HEARING_DEVICES_DISCONNECT,
+ TEST_LAUNCH_SOURCE_ID);
}
@Test
@@ -304,6 +307,7 @@
mDialogDelegate = new HearingDevicesDialogDelegate(
mContext,
true,
+ TEST_LAUNCH_SOURCE_ID,
mDialogFactory,
mActivityStarter,
mDialogTransitionAnimator,
@@ -327,6 +331,7 @@
mDialogDelegate = new HearingDevicesDialogDelegate(
mContext,
false,
+ TEST_LAUNCH_SOURCE_ID,
mDialogFactory,
mActivityStarter,
mDialogTransitionAnimator,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java
index a18d272..aa8c6b7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java
@@ -57,6 +57,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.ambient.touch.dagger.InputSessionComponent;
import com.android.systemui.kosmos.KosmosJavaAdapter;
+import com.android.systemui.log.LogBufferHelperKt;
import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.display.DisplayHelper;
@@ -153,7 +154,8 @@
when(mWindowManager.getMaximumWindowMetrics()).thenReturn(mWindowMetrics);
mMonitor = new TouchMonitor(mExecutor, mBackgroundExecutor, mLifecycleRegistry,
mInputFactory, mDisplayHelper, mKosmos.getConfigurationInteractor(),
- handlers, mIWindowManager, 0);
+ handlers, mIWindowManager, 0, "TouchMonitorTest",
+ LogBufferHelperKt.logcatLogBuffer("TouchMonitorTest"));
clearInvocations(mLifecycleRegistry);
mMonitor.init();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
index 1e23690..7889b3c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
@@ -61,10 +61,12 @@
import com.android.systemui.biometrics.ui.viewmodel.CredentialViewModel
import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel
import com.android.systemui.display.data.repository.FakeDisplayRepository
+import com.android.systemui.haptics.msdl.msdlPlayer
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.res.R
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.statusbar.events.ANIMATING_OUT
+import com.android.systemui.testKosmos
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.time.FakeSystemClock
@@ -145,6 +147,9 @@
private val credentialViewModel = CredentialViewModel(mContext, bpCredentialInteractor)
private val defaultLogoIcon = context.getDrawable(R.drawable.ic_android)
+ private val kosmos = testKosmos()
+ private val msdlPlayer = kosmos.msdlPlayer
+
private var authContainer: TestAuthContainerView? = null
@Before
@@ -668,7 +673,8 @@
{ credentialViewModel },
fakeExecutor,
vibrator,
- lazyViewCapture
+ lazyViewCapture,
+ msdlPlayer,
) {
override fun postOnAnimation(runnable: Runnable) {
runnable.run()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
index 4fc4166..55fd344 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
@@ -37,12 +37,15 @@
import android.hardware.face.FaceSensorPropertiesInternal
import android.hardware.fingerprint.FingerprintSensorProperties
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
+import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.view.HapticFeedbackConstants
import android.view.MotionEvent
import android.view.Surface
import androidx.test.filters.SmallTest
import com.android.app.activityTaskManager
+import com.android.keyguard.AuthInteractionProperties
+import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.biometrics.Utils.toBitmap
@@ -72,6 +75,7 @@
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
import com.android.systemui.util.mockito.withArgCaptor
+import com.google.android.msdl.data.model.MSDLToken
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.first
@@ -124,6 +128,7 @@
private val defaultLogoDescriptionFromActivityInfo = "Test Coke App"
private val logoDescriptionFromApp = "Test Cake App"
private val packageNameForLogoWithOverrides = "should.use.overridden.logo"
+ private val authInteractionProperties = AuthInteractionProperties()
/** Prompt panel size padding */
private val smallHorizontalGuidelinePadding =
@@ -707,31 +712,66 @@
}
@Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun set_haptic_on_confirm_when_confirmation_required_otherwise_on_authenticated() =
runGenericTest {
val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false)
kosmos.promptViewModel.showAuthenticated(testCase.authenticatedModality, 1_000L)
- val confirmHaptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
- assertThat(confirmHaptics?.hapticFeedbackConstant)
- .isEqualTo(
- if (expectConfirmation) HapticFeedbackConstants.NO_HAPTICS
- else HapticFeedbackConstants.BIOMETRIC_CONFIRM
- )
- assertThat(confirmHaptics?.flag).isNull()
+ val hapticsPreConfirm by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+ if (expectConfirmation) {
+ assertThat(hapticsPreConfirm).isEqualTo(PromptViewModel.HapticsToPlay.None)
+ } else {
+ val confirmHaptics =
+ hapticsPreConfirm as PromptViewModel.HapticsToPlay.HapticConstant
+ assertThat(confirmHaptics.constant)
+ .isEqualTo(HapticFeedbackConstants.BIOMETRIC_CONFIRM)
+ assertThat(confirmHaptics.flag).isNull()
+ }
if (expectConfirmation) {
kosmos.promptViewModel.confirmAuthenticated()
}
- val confirmedHaptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
- assertThat(confirmedHaptics?.hapticFeedbackConstant)
+ val hapticsPostConfirm by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+ val confirmedHaptics =
+ hapticsPostConfirm as PromptViewModel.HapticsToPlay.HapticConstant
+ assertThat(confirmedHaptics.constant)
.isEqualTo(HapticFeedbackConstants.BIOMETRIC_CONFIRM)
- assertThat(confirmedHaptics?.flag).isNull()
+ assertThat(confirmedHaptics.flag).isNull()
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun set_msdl_haptic_on_confirm_when_confirmation_required_otherwise_on_authenticated() =
+ runGenericTest {
+ val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false)
+
+ kosmos.promptViewModel.showAuthenticated(testCase.authenticatedModality, 1_000L)
+
+ val hapticsPreConfirm by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+
+ if (expectConfirmation) {
+ assertThat(hapticsPreConfirm).isEqualTo(PromptViewModel.HapticsToPlay.None)
+ } else {
+ val confirmHaptics = hapticsPreConfirm as PromptViewModel.HapticsToPlay.MSDL
+ assertThat(confirmHaptics.token).isEqualTo(MSDLToken.UNLOCK)
+ assertThat(confirmHaptics.properties).isEqualTo(authInteractionProperties)
+ }
+
+ if (expectConfirmation) {
+ kosmos.promptViewModel.confirmAuthenticated()
+ }
+
+ val hapticsPostConfirm by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+ val confirmedHaptics = hapticsPostConfirm as PromptViewModel.HapticsToPlay.MSDL
+ assertThat(confirmedHaptics.token).isEqualTo(MSDLToken.UNLOCK)
+ assertThat(confirmedHaptics.properties).isEqualTo(authInteractionProperties)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playSuccessHaptic_SetsConfirmConstant() = runGenericTest {
val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false)
kosmos.promptViewModel.showAuthenticated(testCase.authenticatedModality, 1_000L)
@@ -740,20 +780,48 @@
kosmos.promptViewModel.confirmAuthenticated()
}
- val currentHaptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
- assertThat(currentHaptics?.hapticFeedbackConstant)
- .isEqualTo(HapticFeedbackConstants.BIOMETRIC_CONFIRM)
- assertThat(currentHaptics?.flag).isNull()
+ val haptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+ val currentHaptics = haptics as PromptViewModel.HapticsToPlay.HapticConstant
+ assertThat(currentHaptics.constant).isEqualTo(HapticFeedbackConstants.BIOMETRIC_CONFIRM)
+ assertThat(currentHaptics.flag).isNull()
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playSuccessHaptic_SetsUnlockMSDLFeedback() = runGenericTest {
+ val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false)
+ kosmos.promptViewModel.showAuthenticated(testCase.authenticatedModality, 1_000L)
+
+ if (expectConfirmation) {
+ kosmos.promptViewModel.confirmAuthenticated()
+ }
+
+ val haptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+ val currentHaptics = haptics as PromptViewModel.HapticsToPlay.MSDL
+ assertThat(currentHaptics.token).isEqualTo(MSDLToken.UNLOCK)
+ assertThat(currentHaptics.properties).isEqualTo(authInteractionProperties)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playErrorHaptic_SetsRejectConstant() = runGenericTest {
kosmos.promptViewModel.showTemporaryError("test", "messageAfterError", false)
- val currentHaptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
- assertThat(currentHaptics?.hapticFeedbackConstant)
- .isEqualTo(HapticFeedbackConstants.BIOMETRIC_REJECT)
- assertThat(currentHaptics?.flag).isNull()
+ val haptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+ val currentHaptics = haptics as PromptViewModel.HapticsToPlay.HapticConstant
+ assertThat(currentHaptics.constant).isEqualTo(HapticFeedbackConstants.BIOMETRIC_REJECT)
+ assertThat(currentHaptics.flag).isNull()
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playErrorHaptic_SetsFailureMSDLFeedback() = runGenericTest {
+ kosmos.promptViewModel.showTemporaryError("test", "messageAfterError", false)
+
+ val haptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+ val currentHaptics = haptics as PromptViewModel.HapticsToPlay.MSDL
+ assertThat(currentHaptics.token).isEqualTo(MSDLToken.FAILURE)
+ assertThat(currentHaptics.properties).isEqualTo(authInteractionProperties)
}
// biometricprompt_sfps_fingerprint_authenticating reused across rotations
@@ -855,6 +923,7 @@
}
@Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun set_haptic_on_errors() = runGenericTest {
kosmos.promptViewModel.showTemporaryError(
"so sad",
@@ -863,13 +932,30 @@
hapticFeedback = true,
)
- val haptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
- assertThat(haptics?.hapticFeedbackConstant)
- .isEqualTo(HapticFeedbackConstants.BIOMETRIC_REJECT)
- assertThat(haptics?.flag).isNull()
+ val hapticsToPlay by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+ val haptics = hapticsToPlay as PromptViewModel.HapticsToPlay.HapticConstant
+ assertThat(haptics.constant).isEqualTo(HapticFeedbackConstants.BIOMETRIC_REJECT)
+ assertThat(haptics.flag).isNull()
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun set_msdl_haptic_on_errors() = runGenericTest {
+ kosmos.promptViewModel.showTemporaryError(
+ "so sad",
+ messageAfterError = "",
+ authenticateAfterError = false,
+ hapticFeedback = true,
+ )
+
+ val hapticsToPlay by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+ val haptics = hapticsToPlay as PromptViewModel.HapticsToPlay.MSDL
+ assertThat(haptics.token).isEqualTo(MSDLToken.FAILURE)
+ assertThat(haptics.properties).isEqualTo(authInteractionProperties)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun plays_haptic_on_errors_unless_skipped() = runGenericTest {
kosmos.promptViewModel.showTemporaryError(
"still sad",
@@ -878,11 +964,26 @@
hapticFeedback = false,
)
- val haptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
- assertThat(haptics?.hapticFeedbackConstant).isEqualTo(HapticFeedbackConstants.NO_HAPTICS)
+ val hapticsToPlay by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+ assertThat(hapticsToPlay).isEqualTo(PromptViewModel.HapticsToPlay.None)
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun plays_msdl_haptic_on_errors_unless_skipped() = runGenericTest {
+ kosmos.promptViewModel.showTemporaryError(
+ "still sad",
+ messageAfterError = "",
+ authenticateAfterError = false,
+ hapticFeedback = false,
+ )
+
+ val hapticsToPlay by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+ assertThat(hapticsToPlay).isEqualTo(PromptViewModel.HapticsToPlay.None)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun plays_haptic_on_error_after_auth_when_confirmation_needed() = runGenericTest {
val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false)
kosmos.promptViewModel.showAuthenticated(testCase.authenticatedModality, 0)
@@ -894,17 +995,39 @@
hapticFeedback = true,
)
- val haptics by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+ val hapticsToPlay by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+ val haptics = hapticsToPlay as PromptViewModel.HapticsToPlay.HapticConstant
if (expectConfirmation) {
- assertThat(haptics?.hapticFeedbackConstant)
- .isEqualTo(HapticFeedbackConstants.BIOMETRIC_REJECT)
- assertThat(haptics?.flag).isNull()
+ assertThat(haptics.constant).isEqualTo(HapticFeedbackConstants.BIOMETRIC_REJECT)
+ assertThat(haptics.flag).isNull()
} else {
- assertThat(haptics?.hapticFeedbackConstant)
- .isEqualTo(HapticFeedbackConstants.BIOMETRIC_CONFIRM)
+ assertThat(haptics.constant).isEqualTo(HapticFeedbackConstants.BIOMETRIC_CONFIRM)
}
}
+ @Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun plays_msdl_haptic_on_error_after_auth_when_confirmation_needed() = runGenericTest {
+ val expectConfirmation = testCase.expectConfirmation(atLeastOneFailure = false)
+ kosmos.promptViewModel.showAuthenticated(testCase.authenticatedModality, 0)
+
+ kosmos.promptViewModel.showTemporaryError(
+ "still sad",
+ messageAfterError = "",
+ authenticateAfterError = false,
+ hapticFeedback = true,
+ )
+
+ val hapticsToPlay by collectLastValue(kosmos.promptViewModel.hapticsToPlay)
+ val haptics = hapticsToPlay as PromptViewModel.HapticsToPlay.MSDL
+ if (expectConfirmation) {
+ assertThat(haptics.token).isEqualTo(MSDLToken.FAILURE)
+ } else {
+ assertThat(haptics.token).isEqualTo(MSDLToken.UNLOCK)
+ }
+ assertThat(haptics.properties).isEqualTo(authInteractionProperties)
+ }
+
private suspend fun TestScope.showTemporaryErrors(
restart: Boolean,
helpAfterError: String = "",
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerPredictiveBackTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerPredictiveBackTest.kt
new file mode 100644
index 0000000..22946c8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/composable/BouncerPredictiveBackTest.kt
@@ -0,0 +1,348 @@
+/*
+ * 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.bouncer.ui.composable
+
+import android.app.AlertDialog
+import android.platform.test.annotations.MotionTest
+import android.testing.TestableLooper.RunWithLooper
+import androidx.activity.BackEventCompat
+import androidx.compose.animation.core.Animatable
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.layout.Box
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.isFinite
+import androidx.compose.ui.geometry.isUnspecified
+import androidx.compose.ui.semantics.SemanticsNode
+import androidx.compose.ui.test.junit4.AndroidComposeTestRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import com.android.compose.animation.scene.ObservableTransitionState
+import com.android.compose.animation.scene.Scale
+import com.android.compose.animation.scene.SceneKey
+import com.android.compose.animation.scene.SceneScope
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
+import com.android.compose.animation.scene.isElement
+import com.android.compose.animation.scene.testing.lastAlphaForTesting
+import com.android.compose.animation.scene.testing.lastScaleForTesting
+import com.android.compose.theme.PlatformTheme
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.domain.interactor.bouncerInteractor
+import com.android.systemui.bouncer.ui.BouncerDialogFactory
+import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel
+import com.android.systemui.bouncer.ui.viewmodel.BouncerUserActionsViewModel
+import com.android.systemui.bouncer.ui.viewmodel.bouncerSceneContentViewModel
+import com.android.systemui.classifier.domain.interactor.falsingInteractor
+import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.lifecycle.ExclusiveActivatable
+import com.android.systemui.lifecycle.rememberViewModel
+import com.android.systemui.motion.createSysUiComposeMotionTestRule
+import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.domain.startable.sceneContainerStartable
+import com.android.systemui.scene.shared.logger.sceneLogger
+import com.android.systemui.scene.shared.model.SceneContainerConfig
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.scene.shared.model.sceneDataSourceDelegator
+import com.android.systemui.scene.ui.composable.Scene
+import com.android.systemui.scene.ui.composable.SceneContainer
+import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
+import com.android.systemui.scene.ui.viewmodel.splitEdgeDetector
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.testKosmos
+import kotlinx.coroutines.awaitCancellation
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
+import org.json.JSONObject
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.MockitoAnnotations
+import platform.test.motion.compose.ComposeFeatureCaptures.positionInRoot
+import platform.test.motion.compose.ComposeRecordingSpec
+import platform.test.motion.compose.MotionControl
+import platform.test.motion.compose.feature
+import platform.test.motion.compose.recordMotion
+import platform.test.motion.compose.runTest
+import platform.test.motion.golden.DataPoint
+import platform.test.motion.golden.DataPointType
+import platform.test.motion.golden.DataPointTypes
+import platform.test.motion.golden.FeatureCapture
+import platform.test.motion.golden.UnknownTypeException
+import platform.test.screenshot.DeviceEmulationSpec
+import platform.test.screenshot.Displays.Phone
+
+/** MotionTest for the Bouncer Predictive Back animation */
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+@RunWithLooper
+@EnableSceneContainer
+@MotionTest
+class BouncerPredictiveBackTest : SysuiTestCase() {
+
+ private val deviceSpec = DeviceEmulationSpec(Phone)
+ private val kosmos = testKosmos()
+
+ @get:Rule val motionTestRule = createSysUiComposeMotionTestRule(kosmos, deviceSpec)
+ private val androidComposeTestRule =
+ motionTestRule.toolkit.composeContentTestRule as AndroidComposeTestRule<*, *>
+
+ private val sceneInteractor by lazy { kosmos.sceneInteractor }
+ private val Kosmos.sceneKeys by Fixture { listOf(Scenes.Lockscreen, Scenes.Bouncer) }
+ private val Kosmos.initialSceneKey by Fixture { Scenes.Bouncer }
+ private val Kosmos.sceneContainerConfig by Fixture {
+ val navigationDistances =
+ mapOf(
+ Scenes.Lockscreen to 1,
+ Scenes.Bouncer to 0,
+ )
+ SceneContainerConfig(sceneKeys, initialSceneKey, emptyList(), navigationDistances)
+ }
+
+ private val transitionState by lazy {
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Idle(kosmos.sceneContainerConfig.initialSceneKey)
+ )
+ }
+ private val sceneContainerViewModel by lazy {
+ SceneContainerViewModel(
+ sceneInteractor = kosmos.sceneInteractor,
+ falsingInteractor = kosmos.falsingInteractor,
+ powerInteractor = kosmos.powerInteractor,
+ shadeInteractor = kosmos.shadeInteractor,
+ splitEdgeDetector = kosmos.splitEdgeDetector,
+ logger = kosmos.sceneLogger,
+ motionEventHandlerReceiver = {},
+ )
+ .apply { setTransitionState(transitionState) }
+ }
+
+ private val bouncerDialogFactory =
+ object : BouncerDialogFactory {
+ override fun invoke(): AlertDialog {
+ throw AssertionError()
+ }
+ }
+ private val bouncerSceneActionsViewModelFactory =
+ object : BouncerUserActionsViewModel.Factory {
+ override fun create() = BouncerUserActionsViewModel(kosmos.bouncerInteractor)
+ }
+ private lateinit var bouncerSceneContentViewModel: BouncerSceneContentViewModel
+ private val bouncerSceneContentViewModelFactory =
+ object : BouncerSceneContentViewModel.Factory {
+ override fun create() = bouncerSceneContentViewModel
+ }
+ private val bouncerScene =
+ BouncerScene(
+ bouncerSceneActionsViewModelFactory,
+ bouncerSceneContentViewModelFactory,
+ bouncerDialogFactory
+ )
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ bouncerSceneContentViewModel = kosmos.bouncerSceneContentViewModel
+
+ val startable = kosmos.sceneContainerStartable
+ startable.start()
+ }
+
+ @Test
+ fun bouncerPredictiveBackMotion() =
+ motionTestRule.runTest {
+ val motion =
+ recordMotion(
+ content = { play ->
+ PlatformTheme {
+ BackGestureAnimation(play)
+ SceneContainer(
+ viewModel =
+ rememberViewModel("BouncerPredictiveBackTest") {
+ sceneContainerViewModel
+ },
+ sceneByKey =
+ mapOf(
+ Scenes.Lockscreen to FakeLockscreen(),
+ Scenes.Bouncer to bouncerScene
+ ),
+ initialSceneKey = Scenes.Bouncer,
+ overlayByKey = emptyMap(),
+ dataSourceDelegator = kosmos.sceneDataSourceDelegator
+ )
+ }
+ },
+ ComposeRecordingSpec(
+ MotionControl(
+ delayRecording = {
+ awaitCondition {
+ sceneInteractor.transitionState.value.isTransitioning()
+ }
+ }
+ ) {
+ awaitCondition {
+ sceneInteractor.transitionState.value.isIdle(Scenes.Lockscreen)
+ }
+ }
+ ) {
+ feature(isElement(Bouncer.Elements.Content), elementAlpha, "content_alpha")
+ feature(isElement(Bouncer.Elements.Content), elementScale, "content_scale")
+ feature(
+ isElement(Bouncer.Elements.Content),
+ positionInRoot,
+ "content_offset"
+ )
+ feature(
+ isElement(Bouncer.Elements.Background),
+ elementAlpha,
+ "background_alpha"
+ )
+ }
+ )
+
+ assertThat(motion).timeSeriesMatchesGolden()
+ }
+
+ @Composable
+ private fun BackGestureAnimation(play: Boolean) {
+ val backProgress = remember { Animatable(0f) }
+
+ LaunchedEffect(play) {
+ if (play) {
+ val dispatcher = androidComposeTestRule.activity.onBackPressedDispatcher
+ androidComposeTestRule.runOnUiThread {
+ dispatcher.dispatchOnBackStarted(backEvent())
+ }
+ backProgress.animateTo(
+ targetValue = 1f,
+ animationSpec = tween(durationMillis = 500)
+ ) {
+ androidComposeTestRule.runOnUiThread {
+ dispatcher.dispatchOnBackProgressed(
+ backEvent(progress = backProgress.value)
+ )
+ if (backProgress.value == 1f) {
+ dispatcher.onBackPressed()
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private fun backEvent(progress: Float = 0f): BackEventCompat {
+ return BackEventCompat(
+ touchX = 0f,
+ touchY = 0f,
+ progress = progress,
+ swipeEdge = BackEventCompat.EDGE_LEFT,
+ )
+ }
+
+ private class FakeLockscreen : ExclusiveActivatable(), Scene {
+ override val key: SceneKey = Scenes.Lockscreen
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = flowOf()
+
+ @Composable
+ override fun SceneScope.Content(modifier: Modifier) {
+ Box(modifier = modifier, contentAlignment = Alignment.Center) {
+ Text(text = "Fake Lockscreen")
+ }
+ }
+
+ override suspend fun onActivated() = awaitCancellation()
+ }
+
+ companion object {
+ private val elementAlpha =
+ FeatureCapture<SemanticsNode, Float>("alpha") {
+ DataPoint.of(it.lastAlphaForTesting, DataPointTypes.float)
+ }
+
+ private val elementScale =
+ FeatureCapture<SemanticsNode, Scale>("scale") {
+ DataPoint.of(it.lastScaleForTesting, scale)
+ }
+
+ private val scale: DataPointType<Scale> =
+ DataPointType(
+ "scale",
+ jsonToValue = {
+ when (it) {
+ "unspecified" -> Scale.Unspecified
+ "default" -> Scale.Default
+ "zero" -> Scale.Zero
+ is JSONObject -> {
+ val pivot = it.get("pivot")
+ Scale(
+ scaleX = it.getDouble("x").toFloat(),
+ scaleY = it.getDouble("y").toFloat(),
+ pivot =
+ when (pivot) {
+ "unspecified" -> Offset.Unspecified
+ "infinite" -> Offset.Infinite
+ is JSONObject ->
+ Offset(
+ pivot.getDouble("x").toFloat(),
+ pivot.getDouble("y").toFloat()
+ )
+ else -> throw UnknownTypeException()
+ }
+ )
+ }
+ else -> throw UnknownTypeException()
+ }
+ },
+ valueToJson = {
+ when (it) {
+ Scale.Unspecified -> "unspecified"
+ Scale.Default -> "default"
+ Scale.Zero -> "zero"
+ else -> {
+ JSONObject().apply {
+ put("x", it.scaleX)
+ put("y", it.scaleY)
+ put(
+ "pivot",
+ when {
+ it.pivot.isUnspecified -> "unspecified"
+ !it.pivot.isFinite -> "infinite"
+ else ->
+ JSONObject().apply {
+ put("x", it.pivot.x)
+ put("y", it.pivot.y)
+ }
+ }
+ )
+ }
+ }
+ }
+ }
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
index 88bfcf0..6377717 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
@@ -39,8 +39,6 @@
import com.android.internal.logging.testing.FakeMetricsLogger;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingDataProvider.GestureFinalizedListener;
-import com.android.systemui.flags.FakeFeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
@@ -84,7 +82,6 @@
private AccessibilityManager mAccessibilityManager;
private final FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
- private final FakeFeatureFlags mFakeFeatureFlags = new FakeFeatureFlags();
private final FalsingClassifier.Result mFalsedResult =
FalsingClassifier.Result.falsed(1, getClass().getSimpleName(), "");
@@ -107,10 +104,11 @@
when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList);
when(mKeyguardStateController.isShowing()).thenReturn(true);
when(mFalsingDataProvider.isUnfolded()).thenReturn(false);
+ when(mFalsingDataProvider.isTouchScreenSource()).thenReturn(true);
mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider,
mMetricsLogger, mClassifiers, mSingleTapClassfier, mLongTapClassifier,
mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController,
- mAccessibilityManager, false, mFakeFeatureFlags);
+ mAccessibilityManager, false);
ArgumentCaptor<GestureFinalizedListener> gestureCompleteListenerCaptor =
@@ -120,7 +118,6 @@
gestureCompleteListenerCaptor.capture());
mGestureFinalizedListener = gestureCompleteListenerCaptor.getValue();
- mFakeFeatureFlags.set(Flags.FALSING_OFF_FOR_UNFOLDED, true);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt
index 933ddb5..4a80d72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt
@@ -21,7 +21,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.haptics.vibratorHelper
+import com.android.systemui.haptics.fakeVibratorHelper
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.fakeSystemClock
@@ -47,6 +47,7 @@
private val lowTickDuration = 12 // Mocked duration of a low tick
private val dragTextureThresholdMillis =
lowTickDuration * config.numberOfLowTicks + config.deltaMillisForDragInterval
+ private val vibratorHelper = kosmos.fakeVibratorHelper
private lateinit var sliderHapticFeedbackProvider: SliderHapticFeedbackProvider
@Before
@@ -56,11 +57,11 @@
whenever(velocityTracker.getAxisVelocity(config.velocityAxis))
.thenReturn(config.maxVelocityToScale)
- kosmos.vibratorHelper.primitiveDurations[VibrationEffect.Composition.PRIMITIVE_LOW_TICK] =
+ vibratorHelper.primitiveDurations[VibrationEffect.Composition.PRIMITIVE_LOW_TICK] =
lowTickDuration
sliderHapticFeedbackProvider =
SliderHapticFeedbackProvider(
- kosmos.vibratorHelper,
+ vibratorHelper,
velocityTracker,
config,
kosmos.fakeSystemClock,
@@ -136,7 +137,7 @@
sliderHapticFeedbackProvider.onUpperBookend()
sliderHapticFeedbackProvider.onUpperBookend()
- assertEquals(/* expected=*/ 1, vibratorHelper.timesVibratedWithEffect(vibration))
+ assertEquals(/* expected= */ 1, vibratorHelper.timesVibratedWithEffect(vibration))
}
@Test
@@ -162,7 +163,7 @@
sliderHapticFeedbackProvider.onProgress(progress)
// THEN the correct composition only plays once
- assertEquals(/* expected=*/ 1, vibratorHelper.timesVibratedWithEffect(ticks.compose()))
+ assertEquals(/* expected= */ 1, vibratorHelper.timesVibratedWithEffect(ticks.compose()))
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialNotificationCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialNotificationCoordinatorTest.kt
new file mode 100644
index 0000000..945f953
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialNotificationCoordinatorTest.kt
@@ -0,0 +1,158 @@
+/*
+ * 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.inputdevice.tutorial.domain.interactor
+
+import android.app.Notification
+import android.app.NotificationManager
+import androidx.annotation.StringRes
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.inputdevice.tutorial.data.repository.TutorialSchedulerRepository
+import com.android.systemui.inputdevice.tutorial.ui.TutorialNotificationCoordinator
+import com.android.systemui.keyboard.data.repository.FakeKeyboardRepository
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.res.R
+import com.android.systemui.touchpad.data.repository.FakeTouchpadRepository
+import com.google.common.truth.Truth.assertThat
+import kotlin.time.Duration.Companion.hours
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.runTest
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.junit.MockitoJUnit
+import org.mockito.kotlin.any
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.never
+import org.mockito.kotlin.verify
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class TutorialNotificationCoordinatorTest : SysuiTestCase() {
+
+ private lateinit var underTest: TutorialNotificationCoordinator
+ private val kosmos = Kosmos()
+ private val testScope = kosmos.testScope
+ private val keyboardRepository = FakeKeyboardRepository()
+ private val touchpadRepository = FakeTouchpadRepository()
+ private lateinit var dataStoreScope: CoroutineScope
+ private lateinit var repository: TutorialSchedulerRepository
+ @Mock private lateinit var notificationManager: NotificationManager
+ @Captor private lateinit var notificationCaptor: ArgumentCaptor<Notification>
+ @get:Rule val rule = MockitoJUnit.rule()
+
+ @Before
+ fun setup() {
+ dataStoreScope = CoroutineScope(Dispatchers.Unconfined)
+ repository =
+ TutorialSchedulerRepository(
+ context,
+ dataStoreScope,
+ dataStoreName = "TutorialNotificationCoordinatorTest"
+ )
+ val interactor =
+ TutorialSchedulerInteractor(keyboardRepository, touchpadRepository, repository)
+ underTest =
+ TutorialNotificationCoordinator(
+ testScope.backgroundScope,
+ context,
+ interactor,
+ notificationManager
+ )
+ notificationCaptor = ArgumentCaptor.forClass(Notification::class.java)
+ underTest.start()
+ }
+
+ @After
+ fun clear() {
+ runBlocking { repository.clearDataStore() }
+ dataStoreScope.cancel()
+ }
+
+ @Test
+ fun showKeyboardNotification() =
+ testScope.runTest {
+ keyboardRepository.setIsAnyKeyboardConnected(true)
+ advanceTimeBy(LAUNCH_DELAY)
+ verifyNotification(
+ R.string.launch_keyboard_tutorial_notification_title,
+ R.string.launch_keyboard_tutorial_notification_content
+ )
+ }
+
+ @Test
+ fun showTouchpadNotification() =
+ testScope.runTest {
+ touchpadRepository.setIsAnyTouchpadConnected(true)
+ advanceTimeBy(LAUNCH_DELAY)
+ verifyNotification(
+ R.string.launch_touchpad_tutorial_notification_title,
+ R.string.launch_touchpad_tutorial_notification_content
+ )
+ }
+
+ @Test
+ fun showKeyboardTouchpadNotification() =
+ testScope.runTest {
+ keyboardRepository.setIsAnyKeyboardConnected(true)
+ touchpadRepository.setIsAnyTouchpadConnected(true)
+ advanceTimeBy(LAUNCH_DELAY)
+ verifyNotification(
+ R.string.launch_keyboard_touchpad_tutorial_notification_title,
+ R.string.launch_keyboard_touchpad_tutorial_notification_content
+ )
+ }
+
+ @Test
+ fun doNotShowNotification() =
+ testScope.runTest {
+ advanceTimeBy(LAUNCH_DELAY)
+ verify(notificationManager, never()).notify(eq(TAG), eq(NOTIFICATION_ID), any())
+ }
+
+ private fun verifyNotification(@StringRes titleResId: Int, @StringRes contentResId: Int) {
+ verify(notificationManager)
+ .notify(eq(TAG), eq(NOTIFICATION_ID), notificationCaptor.capture())
+ val notification = notificationCaptor.value
+ val actualTitle = notification.getString(Notification.EXTRA_TITLE)
+ val actualContent = notification.getString(Notification.EXTRA_TEXT)
+ assertThat(actualTitle).isEqualTo(context.getString(titleResId))
+ assertThat(actualContent).isEqualTo(context.getString(contentResId))
+ }
+
+ private fun Notification.getString(key: String): String =
+ this.extras?.getCharSequence(key).toString()
+
+ companion object {
+ private const val TAG = "TutorialSchedulerInteractor"
+ private const val NOTIFICATION_ID = 5566
+ private val LAUNCH_DELAY = 72.hours
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt
index 432f7af..650f9dc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt
@@ -32,6 +32,8 @@
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.cancel
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runTest
@@ -63,13 +65,7 @@
dataStoreName = "TutorialSchedulerInteractorTest"
)
underTest =
- TutorialSchedulerInteractor(
- testScope.backgroundScope,
- keyboardRepository,
- touchpadRepository,
- schedulerRepository
- )
- underTest.start()
+ TutorialSchedulerInteractor(keyboardRepository, touchpadRepository, schedulerRepository)
}
@After
@@ -81,80 +77,90 @@
@Test
fun connectKeyboard_delayElapse_launchForKeyboard() =
testScope.runTest {
+ launchAndAssert(TutorialType.KEYBOARD)
+
keyboardRepository.setIsAnyKeyboardConnected(true)
advanceTimeBy(LAUNCH_DELAY)
- assertLaunch(TutorialType.KEYBOARD)
}
@Test
fun connectBothDevices_delayElapse_launchForBoth() =
testScope.runTest {
+ launchAndAssert(TutorialType.BOTH)
+
keyboardRepository.setIsAnyKeyboardConnected(true)
touchpadRepository.setIsAnyTouchpadConnected(true)
advanceTimeBy(LAUNCH_DELAY)
- assertLaunch(TutorialType.BOTH)
}
@Test
fun connectBothDevice_delayNotElapse_launchNothing() =
testScope.runTest {
+ launchAndAssert(TutorialType.NONE)
+
keyboardRepository.setIsAnyKeyboardConnected(true)
touchpadRepository.setIsAnyTouchpadConnected(true)
advanceTimeBy(A_SHORT_PERIOD_OF_TIME)
- assertLaunch(TutorialType.NONE)
}
@Test
fun nothingConnect_delayElapse_launchNothing() =
testScope.runTest {
+ launchAndAssert(TutorialType.NONE)
+
keyboardRepository.setIsAnyKeyboardConnected(false)
touchpadRepository.setIsAnyTouchpadConnected(false)
advanceTimeBy(LAUNCH_DELAY)
- assertLaunch(TutorialType.NONE)
}
@Test
fun connectKeyboard_thenTouchpad_delayElapse_launchForBoth() =
testScope.runTest {
+ launchAndAssert(TutorialType.BOTH)
+
keyboardRepository.setIsAnyKeyboardConnected(true)
advanceTimeBy(A_SHORT_PERIOD_OF_TIME)
touchpadRepository.setIsAnyTouchpadConnected(true)
advanceTimeBy(REMAINING_TIME)
- assertLaunch(TutorialType.BOTH)
}
@Test
fun connectKeyboard_thenTouchpad_removeKeyboard_delayElapse_launchNothing() =
testScope.runTest {
+ launchAndAssert(TutorialType.NONE)
+
keyboardRepository.setIsAnyKeyboardConnected(true)
advanceTimeBy(A_SHORT_PERIOD_OF_TIME)
touchpadRepository.setIsAnyTouchpadConnected(true)
keyboardRepository.setIsAnyKeyboardConnected(false)
advanceTimeBy(REMAINING_TIME)
- assertLaunch(TutorialType.NONE)
}
- // TODO: likely to be changed after we update TutorialSchedulerInteractor.launchTutorial
- private suspend fun assertLaunch(tutorialType: TutorialType) {
- when (tutorialType) {
- TutorialType.KEYBOARD -> {
- assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isTrue()
- assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isFalse()
- }
- TutorialType.TOUCHPAD -> {
- assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isFalse()
- assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isTrue()
- }
- TutorialType.BOTH -> {
- assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isTrue()
- assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isTrue()
- }
- TutorialType.NONE -> {
- assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isFalse()
- assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isFalse()
+ private suspend fun launchAndAssert(expectedTutorial: TutorialType) =
+ testScope.backgroundScope.launch {
+ val actualTutorial = underTest.tutorials.first()
+ assertThat(actualTutorial).isEqualTo(expectedTutorial)
+
+ // TODO: need to update after we move launch into the tutorial
+ when (expectedTutorial) {
+ TutorialType.KEYBOARD -> {
+ assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isTrue()
+ assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isFalse()
+ }
+ TutorialType.TOUCHPAD -> {
+ assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isFalse()
+ assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isTrue()
+ }
+ TutorialType.BOTH -> {
+ assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isTrue()
+ assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isTrue()
+ }
+ TutorialType.NONE -> {
+ assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isFalse()
+ assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isFalse()
+ }
}
}
- }
companion object {
private val LAUNCH_DELAY = 72.hours
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
index 7cc9185..bfb8a57 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
@@ -34,6 +34,7 @@
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryBackgroundViewModel
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryForegroundViewModel
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel
+import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.res.R
import com.android.systemui.shade.NotificationPanelView
@@ -86,6 +87,7 @@
{ mock(DeviceEntryBackgroundViewModel::class.java) },
{ falsingManager },
{ mock(VibratorHelper::class.java) },
+ logcatLogBuffer(),
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt
index e55cb12..030b172 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt
@@ -19,8 +19,8 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.log.LogcatEchoTrackerAlways
import com.android.systemui.log.table.TableChange.Companion.IS_INITIAL_PREFIX
-import com.android.systemui.util.mockito.mock
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import java.io.PrintWriter
@@ -57,9 +57,7 @@
MAX_SIZE,
BUFFER_NAME,
systemClock,
- mock(),
- testDispatcher,
- testScope.backgroundScope,
+ LogcatEchoTrackerAlways(),
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt
index 8c62bc2..dfd964f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt
@@ -20,25 +20,20 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
-import com.android.systemui.util.mockito.mock
+import com.android.systemui.log.LogcatEchoTrackerAlways
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.kotlin.mock
-@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
class TableLogBufferFactoryTest : SysuiTestCase() {
private val dumpManager: DumpManager = mock()
private val systemClock = FakeSystemClock()
- private val testDispatcher = UnconfinedTestDispatcher()
- private val testScope = TestScope(testDispatcher)
private val underTest =
- TableLogBufferFactory(dumpManager, systemClock, mock(), testDispatcher, testScope)
+ TableLogBufferFactory(dumpManager, systemClock, LogcatEchoTrackerAlways())
@Test
fun create_alwaysCreatesNewInstance() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt
index ace562b..9c4c862 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt
@@ -23,22 +23,18 @@
import com.android.systemui.log.core.LogLevel
import com.android.systemui.log.table.TableChange.Companion.IS_INITIAL_PREFIX
import com.android.systemui.log.table.TableChange.Companion.MAX_STRING_LENGTH
-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.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import java.io.PrintWriter
import java.io.StringWriter
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
-@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
class TableLogBufferTest : SysuiTestCase() {
@@ -49,9 +45,6 @@
private lateinit var logcatEchoTracker: LogcatEchoTracker
private lateinit var localLogcat: FakeLogProxy
- private val testDispatcher = UnconfinedTestDispatcher()
- private val testScope = TestScope(testDispatcher)
-
@Before
fun setup() {
localLogcat = FakeLogProxy()
@@ -65,8 +58,6 @@
NAME,
systemClock,
logcatEchoTracker,
- testDispatcher,
- testScope.backgroundScope,
localLogcat = localLogcat,
)
}
@@ -78,8 +69,6 @@
"name",
systemClock,
logcatEchoTracker,
- testDispatcher,
- testScope.backgroundScope,
localLogcat = localLogcat,
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
index fd53b5ba..3c74374 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
@@ -56,7 +56,6 @@
import com.android.systemui.flags.Flags.MEDIA_RESUME_PROGRESS
import com.android.systemui.flags.Flags.MEDIA_RETAIN_RECOMMENDATIONS
import com.android.systemui.flags.Flags.MEDIA_RETAIN_SESSIONS
-import com.android.systemui.flags.Flags.MEDIA_SESSION_ACTIONS
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
@@ -317,7 +316,6 @@
whenever(mediaSmartspaceTarget.iconGrid).thenReturn(validRecommendationList)
whenever(mediaSmartspaceTarget.creationTimeMillis).thenReturn(SMARTSPACE_CREATION_TIME)
whenever(mediaSmartspaceTarget.expiryTimeMillis).thenReturn(SMARTSPACE_EXPIRY_TIME)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, false)
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, false)
fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, false)
fakeFeatureFlags.set(MEDIA_REMOTE_RESUME, false)
@@ -969,7 +967,8 @@
assertThat(data.resumption).isTrue()
assertThat(data.song).isEqualTo(SESSION_TITLE)
assertThat(data.app).isEqualTo(APP_NAME)
- assertThat(data.actions).hasSize(1)
+ // resume button is a semantic action.
+ assertThat(data.actions).hasSize(0)
assertThat(data.semanticActions!!.playOrPause).isNotNull()
assertThat(data.lastActive).isAtLeast(currentTime)
verify(logger).logResumeMediaAdded(anyInt(), eq(PACKAGE_NAME), eq(data.instanceId))
@@ -996,7 +995,8 @@
assertThat(data.resumption).isTrue()
assertThat(data.song).isEqualTo(SESSION_TITLE)
assertThat(data.app).isEqualTo(APP_NAME)
- assertThat(data.actions).hasSize(1)
+ // resume button is a semantic action.
+ assertThat(data.actions).hasSize(0)
assertThat(data.semanticActions!!.playOrPause).isNotNull()
assertThat(data.lastActive).isAtLeast(currentTime)
assertThat(data.isExplicit).isTrue()
@@ -1671,7 +1671,6 @@
@Test
fun testPlaybackActions_noState_usesNotification() {
val desc = "Notification Action"
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
whenever(controller.playbackState).thenReturn(null)
val notifWithAction =
@@ -1705,7 +1704,6 @@
@Test
fun testPlaybackActions_hasPrevNext() {
val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4")
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions =
PlaybackState.ACTION_PLAY or
PlaybackState.ACTION_SKIP_TO_PREVIOUS or
@@ -1749,7 +1747,6 @@
@Test
fun testPlaybackActions_noPrevNext_usesCustom() {
val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4", "custom 5")
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions = PlaybackState.ACTION_PLAY
val stateBuilder = PlaybackState.Builder().setActions(stateActions)
customDesc.forEach {
@@ -1781,7 +1778,6 @@
@Test
fun testPlaybackActions_connecting() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions = PlaybackState.ACTION_PLAY
val stateBuilder =
PlaybackState.Builder()
@@ -1802,7 +1798,6 @@
@Test
fun testPlaybackActions_reservedSpace() {
val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4")
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions = PlaybackState.ACTION_PLAY
val stateBuilder = PlaybackState.Builder().setActions(stateActions)
customDesc.forEach {
@@ -1840,7 +1835,6 @@
@Test
fun testPlaybackActions_playPause_hasButton() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions = PlaybackState.ACTION_PLAY_PAUSE
val stateBuilder = PlaybackState.Builder().setActions(stateActions)
whenever(controller.playbackState).thenReturn(stateBuilder.build())
@@ -1939,7 +1933,6 @@
@Test
fun testPlaybackState_PauseWhenFlagTrue_keyExists_callsListener() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val state = PlaybackState.Builder().setState(PlaybackState.STATE_PAUSED, 0L, 1f).build()
whenever(controller.playbackState).thenReturn(state)
@@ -2161,7 +2154,6 @@
@Test
fun testRetain_sessionPlayer_notifRemoved_doesNotChange() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control with PlaybackState actions is added, times out,
@@ -2181,7 +2173,6 @@
@Test
fun testRetain_sessionPlayer_sessionDestroyed_setToResume() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control with PlaybackState actions is added, times out,
@@ -2215,7 +2206,6 @@
@Test
fun testRetain_sessionPlayer_destroyedWhileActive_noResume_fullyRemoved() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control using session actions is added, and then the session is destroyed
@@ -2235,7 +2225,6 @@
@Test
fun testRetain_sessionPlayer_canResume_destroyedWhileActive_setToResume() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control using session actions and that does allow resumption is added,
@@ -2268,7 +2257,6 @@
@Test
fun testSessionPlayer_sessionDestroyed_noResume_fullyRemoved() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control with PlaybackState actions is added, times out,
@@ -2295,7 +2283,6 @@
@Test
fun testSessionPlayer_destroyedWhileActive_noResume_fullyRemoved() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control using session actions is added, and then the session is destroyed
@@ -2314,7 +2301,6 @@
@Test
fun testSessionPlayer_canResume_destroyedWhileActive_setToResume() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control using session actions and that does allow resumption is added,
@@ -2348,7 +2334,6 @@
@Test
fun testSessionDestroyed_noNotificationKey_stillRemoved() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
// When a notiifcation is added and then removed before it is fully processed
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
index f4c2b47..4cf7de3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
@@ -61,7 +61,6 @@
import com.android.systemui.flags.Flags.MEDIA_RESUME_PROGRESS
import com.android.systemui.flags.Flags.MEDIA_RETAIN_RECOMMENDATIONS
import com.android.systemui.flags.Flags.MEDIA_RETAIN_SESSIONS
-import com.android.systemui.flags.Flags.MEDIA_SESSION_ACTIONS
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
@@ -70,6 +69,8 @@
import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
import com.android.systemui.media.controls.domain.resume.MediaResumeListener
import com.android.systemui.media.controls.domain.resume.ResumeMediaBrowser
+import com.android.systemui.media.controls.shared.mediaLogger
+import com.android.systemui.media.controls.shared.mockMediaLogger
import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_SOURCE
import com.android.systemui.media.controls.shared.model.EXTRA_VALUE_TRIGGER_PERIODIC
import com.android.systemui.media.controls.shared.model.MediaData
@@ -141,7 +142,7 @@
@RunWith(ParameterizedAndroidJunit4::class)
@EnableSceneContainer
class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
- private val kosmos = testKosmos()
+ private val kosmos = testKosmos().apply { mediaLogger = mockMediaLogger }
private val testDispatcher = kosmos.testDispatcher
private val testScope = kosmos.testScope
private val settings = kosmos.fakeSettings
@@ -258,6 +259,7 @@
keyguardUpdateMonitor = keyguardUpdateMonitor,
mediaDataRepository = kosmos.mediaDataRepository,
mediaDataLoader = { kosmos.mediaDataLoader },
+ mediaLogger = kosmos.mediaLogger,
)
mediaDataProcessor.start()
testScope.runCurrent()
@@ -338,7 +340,6 @@
whenever(mediaSmartspaceTarget.iconGrid).thenReturn(validRecommendationList)
whenever(mediaSmartspaceTarget.creationTimeMillis).thenReturn(SMARTSPACE_CREATION_TIME)
whenever(mediaSmartspaceTarget.expiryTimeMillis).thenReturn(SMARTSPACE_EXPIRY_TIME)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, false)
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, false)
fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, false)
fakeFeatureFlags.set(MEDIA_REMOTE_RESUME, false)
@@ -986,7 +987,8 @@
assertThat(data.resumption).isTrue()
assertThat(data.song).isEqualTo(SESSION_TITLE)
assertThat(data.app).isEqualTo(APP_NAME)
- assertThat(data.actions).hasSize(1)
+ // resume button is a semantic action.
+ assertThat(data.actions).hasSize(0)
assertThat(data.semanticActions!!.playOrPause).isNotNull()
assertThat(data.lastActive).isAtLeast(currentTime)
verify(logger).logResumeMediaAdded(anyInt(), eq(PACKAGE_NAME), eq(data.instanceId))
@@ -1013,7 +1015,8 @@
assertThat(data.resumption).isTrue()
assertThat(data.song).isEqualTo(SESSION_TITLE)
assertThat(data.app).isEqualTo(APP_NAME)
- assertThat(data.actions).hasSize(1)
+ // resume button is a semantic action.
+ assertThat(data.actions).hasSize(0)
assertThat(data.semanticActions!!.playOrPause).isNotNull()
assertThat(data.lastActive).isAtLeast(currentTime)
assertThat(data.isExplicit).isTrue()
@@ -1680,7 +1683,6 @@
@Test
fun testPlaybackActions_noState_usesNotification() {
val desc = "Notification Action"
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
whenever(controller.playbackState).thenReturn(null)
val notifWithAction =
@@ -1714,7 +1716,6 @@
@Test
fun testPlaybackActions_hasPrevNext() {
val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4")
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions =
PlaybackState.ACTION_PLAY or
PlaybackState.ACTION_SKIP_TO_PREVIOUS or
@@ -1758,7 +1759,6 @@
@Test
fun testPlaybackActions_noPrevNext_usesCustom() {
val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4", "custom 5")
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions = PlaybackState.ACTION_PLAY
val stateBuilder = PlaybackState.Builder().setActions(stateActions)
customDesc.forEach {
@@ -1790,7 +1790,6 @@
@Test
fun testPlaybackActions_connecting() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions = PlaybackState.ACTION_PLAY
val stateBuilder =
PlaybackState.Builder()
@@ -1811,7 +1810,6 @@
@Test
@EnableFlags(Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE)
fun postWithPlaybackActions_drawablesReused() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
val stateActions =
@@ -1845,7 +1843,6 @@
@Test
@DisableFlags(Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE)
fun postWithPlaybackActions_drawablesNotReused() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
val stateActions =
@@ -1879,7 +1876,6 @@
@Test
fun testPlaybackActions_reservedSpace() {
val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4")
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions = PlaybackState.ACTION_PLAY
val stateBuilder = PlaybackState.Builder().setActions(stateActions)
customDesc.forEach {
@@ -1917,7 +1913,6 @@
@Test
fun testPlaybackActions_playPause_hasButton() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions = PlaybackState.ACTION_PLAY_PAUSE
val stateBuilder = PlaybackState.Builder().setActions(stateActions)
whenever(controller.playbackState).thenReturn(stateBuilder.build())
@@ -2016,7 +2011,6 @@
@Test
fun testPlaybackState_PauseWhenFlagTrue_keyExists_callsListener() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val state = PlaybackState.Builder().setState(PlaybackState.STATE_PAUSED, 0L, 1f).build()
whenever(controller.playbackState).thenReturn(state)
@@ -2237,7 +2231,6 @@
@Test
fun testRetain_sessionPlayer_notifRemoved_doesNotChange() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control with PlaybackState actions is added, times out,
@@ -2257,7 +2250,6 @@
@Test
fun testRetain_sessionPlayer_sessionDestroyed_setToResume() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control with PlaybackState actions is added, times out,
@@ -2291,7 +2283,6 @@
@Test
fun testRetain_sessionPlayer_destroyedWhileActive_noResume_fullyRemoved() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control using session actions is added, and then the session is destroyed
@@ -2311,7 +2302,6 @@
@Test
fun testRetain_sessionPlayer_canResume_destroyedWhileActive_setToResume() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control using session actions and that does allow resumption is added,
@@ -2344,7 +2334,6 @@
@Test
fun testSessionPlayer_sessionDestroyed_noResume_fullyRemoved() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control with PlaybackState actions is added, times out,
@@ -2371,7 +2360,6 @@
@Test
fun testSessionPlayer_destroyedWhileActive_noResume_fullyRemoved() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control using session actions is added, and then the session is destroyed
@@ -2390,7 +2378,6 @@
@Test
fun testSessionPlayer_canResume_destroyedWhileActive_setToResume() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control using session actions and that does allow resumption is added,
@@ -2424,7 +2411,6 @@
@Test
fun testSessionDestroyed_noNotificationKey_stillRemoved() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
// When a notiifcation is added and then removed before it is fully processed
mediaDataProcessor.onNotificationAdded(KEY, mediaNotification)
@@ -2495,6 +2481,55 @@
assertThat(mediaDataCaptor.value.artwork).isNull()
}
+ @Test
+ @EnableFlags(Flags.FLAG_MEDIA_CONTROLS_POSTS_OPTIMIZATION)
+ fun postDuplicateNotification_doesNotCallListeners() {
+ whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
+ whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
+
+ mediaDataProcessor.addInternalListener(mediaDataFilter)
+ mediaDataFilter.mediaDataProcessor = mediaDataProcessor
+ addNotificationAndLoad()
+ reset(listener)
+ mediaDataProcessor.onNotificationAdded(KEY, mediaNotification)
+
+ testScope.assertRunAllReady(foreground = 0, background = 1)
+ verify(listener, never())
+ .onMediaDataLoaded(
+ eq(KEY),
+ eq(KEY),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ verify(kosmos.mediaLogger).logDuplicateMediaNotification(eq(KEY))
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MEDIA_CONTROLS_POSTS_OPTIMIZATION)
+ fun postDuplicateNotification_callsListeners() {
+ whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
+ whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
+
+ mediaDataProcessor.addInternalListener(mediaDataFilter)
+ mediaDataFilter.mediaDataProcessor = mediaDataProcessor
+ addNotificationAndLoad()
+ reset(listener)
+ mediaDataProcessor.onNotificationAdded(KEY, mediaNotification)
+ testScope.assertRunAllReady(foreground = 1, background = 1)
+ verify(listener)
+ .onMediaDataLoaded(
+ eq(KEY),
+ eq(KEY),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ verify(kosmos.mediaLogger, never()).logDuplicateMediaNotification(eq(KEY))
+ }
+
private fun TestScope.assertRunAllReady(foreground: Int = 0, background: Int = 0) {
runCurrent()
if (Flags.mediaLoadMetadataViaMediaDataLoader()) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManagerTest.kt
index 0c8d880..6a66c40 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManagerTest.kt
@@ -54,7 +54,6 @@
import com.android.systemui.media.muteawait.MediaMuteAwaitConnectionManagerFactory
import com.android.systemui.res.R
import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.testKosmos
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -126,8 +125,6 @@
private lateinit var mediaData: MediaData
@JvmField @Rule val mockito = MockitoJUnit.rule()
- private val kosmos = testKosmos()
-
@Before
fun setUp() {
fakeFgExecutor = FakeExecutor(FakeSystemClock())
@@ -144,7 +141,6 @@
{ localBluetoothManager },
fakeFgExecutor,
fakeBgExecutor,
- kosmos.mediaDeviceLogger,
)
manager.addListener(listener)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt
index c1bba4d..680df15 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt
@@ -72,7 +72,6 @@
@Mock private lateinit var mediaController: MediaController
@Mock private lateinit var logger: MediaTimeoutLogger
@Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
- private lateinit var executor: FakeExecutor
@Mock private lateinit var timeoutCallback: (String, Boolean) -> Unit
@Mock private lateinit var stateCallback: (String, PlaybackState) -> Unit
@Mock private lateinit var sessionCallback: (String) -> Unit
@@ -88,6 +87,9 @@
private lateinit var resumeData: MediaData
private lateinit var mediaTimeoutListener: MediaTimeoutListener
private var clock = FakeSystemClock()
+ private lateinit var mainExecutor: FakeExecutor
+ private lateinit var bgExecutor: FakeExecutor
+ private lateinit var uiExecutor: FakeExecutor
@Mock private lateinit var mediaFlags: MediaFlags
@Mock private lateinit var smartspaceData: SmartspaceMediaData
@@ -95,11 +97,15 @@
fun setup() {
whenever(mediaControllerFactory.create(any())).thenReturn(mediaController)
whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
- executor = FakeExecutor(clock)
+ mainExecutor = FakeExecutor(clock)
+ bgExecutor = FakeExecutor(clock)
+ uiExecutor = FakeExecutor(clock)
mediaTimeoutListener =
MediaTimeoutListener(
mediaControllerFactory,
- executor,
+ bgExecutor,
+ uiExecutor,
+ mainExecutor,
logger,
statusBarStateController,
clock,
@@ -143,30 +149,31 @@
whenever(playingState.state).thenReturn(PlaybackState.STATE_PLAYING)
whenever(mediaController.playbackState).thenReturn(playingState)
- mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+ loadMediaData(KEY, null, mediaData)
verify(mediaController).registerCallback(capture(mediaCallbackCaptor))
verify(logger).logPlaybackState(eq(KEY), eq(playingState))
// Ignores if same key
clearInvocations(mediaController)
- mediaTimeoutListener.onMediaDataLoaded(KEY, KEY, mediaData)
+ loadMediaData(KEY, KEY, mediaData)
verify(mediaController, never()).registerCallback(anyObject())
}
@Test
fun testOnMediaDataLoaded_registersTimeout_whenPaused() {
- mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+ loadMediaData(KEY, null, mediaData)
verify(mediaController).registerCallback(capture(mediaCallbackCaptor))
- assertThat(executor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
verify(timeoutCallback, never()).invoke(anyString(), anyBoolean())
verify(logger).logScheduleTimeout(eq(KEY), eq(false), eq(false))
- assertThat(executor.advanceClockToNext()).isEqualTo(PAUSED_MEDIA_TIMEOUT)
+ assertThat(mainExecutor.advanceClockToNext()).isEqualTo(PAUSED_MEDIA_TIMEOUT)
}
@Test
fun testOnMediaDataRemoved_unregistersPlaybackListener() {
- mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+ loadMediaData(KEY, null, mediaData)
mediaTimeoutListener.onMediaDataRemoved(KEY, false)
+ assertThat(bgExecutor.runAllReady()).isEqualTo(1)
verify(mediaController).unregisterCallback(anyObject())
// Ignores duplicate requests
@@ -178,50 +185,50 @@
@Test
fun testOnMediaDataRemoved_clearsTimeout() {
// GIVEN media that is paused
- mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
- assertThat(executor.numPending()).isEqualTo(1)
+ loadMediaData(KEY, null, mediaData)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
// WHEN the media is removed
mediaTimeoutListener.onMediaDataRemoved(KEY, false)
// THEN the timeout runnable is cancelled
- assertThat(executor.numPending()).isEqualTo(0)
+ assertThat(mainExecutor.numPending()).isEqualTo(0)
}
@Test
fun testOnMediaDataLoaded_migratesKeys() {
val newKey = "NEWKEY"
// From not playing
- mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+ loadMediaData(KEY, null, mediaData)
clearInvocations(mediaController)
// To playing
val playingState = mock(android.media.session.PlaybackState::class.java)
whenever(playingState.state).thenReturn(PlaybackState.STATE_PLAYING)
whenever(mediaController.playbackState).thenReturn(playingState)
- mediaTimeoutListener.onMediaDataLoaded(newKey, KEY, mediaData)
+ loadMediaData(newKey, KEY, mediaData)
verify(mediaController).unregisterCallback(anyObject())
verify(mediaController).registerCallback(anyObject())
verify(logger).logMigrateListener(eq(KEY), eq(newKey), eq(true))
// Enqueues callback
- assertThat(executor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
}
@Test
fun testOnMediaDataLoaded_migratesKeys_noTimeoutExtension() {
val newKey = "NEWKEY"
// From not playing
- mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+ loadMediaData(KEY, null, mediaData)
clearInvocations(mediaController)
// Migrate, still not playing
val playingState = mock(android.media.session.PlaybackState::class.java)
whenever(playingState.state).thenReturn(PlaybackState.STATE_PAUSED)
whenever(mediaController.playbackState).thenReturn(playingState)
- mediaTimeoutListener.onMediaDataLoaded(newKey, KEY, mediaData)
+ loadMediaData(newKey, KEY, mediaData)
// The number of queued timeout tasks remains the same. The timeout task isn't cancelled nor
// is another scheduled
- assertThat(executor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
verify(logger).logUpdateListener(eq(newKey), eq(false))
}
@@ -233,8 +240,8 @@
mediaCallbackCaptor.value.onPlaybackStateChanged(
PlaybackState.Builder().setState(PlaybackState.STATE_PAUSED, 0L, 0f).build()
)
- assertThat(executor.numPending()).isEqualTo(1)
- assertThat(executor.advanceClockToNext()).isEqualTo(PAUSED_MEDIA_TIMEOUT)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.advanceClockToNext()).isEqualTo(PAUSED_MEDIA_TIMEOUT)
}
@Test
@@ -245,7 +252,7 @@
mediaCallbackCaptor.value.onPlaybackStateChanged(
PlaybackState.Builder().setState(PlaybackState.STATE_PLAYING, 0L, 0f).build()
)
- assertThat(executor.numPending()).isEqualTo(0)
+ assertThat(mainExecutor.numPending()).isEqualTo(0)
verify(logger).logTimeoutCancelled(eq(KEY), any())
}
@@ -257,7 +264,7 @@
mediaCallbackCaptor.value.onPlaybackStateChanged(
PlaybackState.Builder().setState(PlaybackState.STATE_STOPPED, 0L, 0f).build()
)
- assertThat(executor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
}
@Test
@@ -265,7 +272,7 @@
// Assuming we're have a pending timeout
testOnPlaybackStateChanged_schedulesTimeout_whenPaused()
- with(executor) {
+ with(mainExecutor) {
advanceClockToNext()
runAllReady()
}
@@ -274,7 +281,7 @@
@Test
fun testIsTimedOut() {
- mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+ loadMediaData(KEY, null, mediaData)
assertThat(mediaTimeoutListener.isTimedOut(KEY)).isFalse()
}
@@ -282,16 +289,17 @@
fun testOnSessionDestroyed_active_clearsTimeout() {
// GIVEN media that is paused
val mediaPaused = mediaData.copy(isPlaying = false)
- mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaPaused)
+ loadMediaData(KEY, null, mediaPaused)
verify(mediaController).registerCallback(capture(mediaCallbackCaptor))
- assertThat(executor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
// WHEN the session is destroyed
mediaCallbackCaptor.value.onSessionDestroyed()
// THEN the controller is unregistered and timeout run
+ assertThat(bgExecutor.runAllReady()).isEqualTo(1)
verify(mediaController).unregisterCallback(anyObject())
- assertThat(executor.numPending()).isEqualTo(0)
+ assertThat(mainExecutor.numPending()).isEqualTo(0)
verify(logger).logSessionDestroyed(eq(KEY))
verify(sessionCallback).invoke(eq(KEY))
}
@@ -306,11 +314,11 @@
whenever(playingState.state).thenReturn(PlaybackState.STATE_PLAYING)
whenever(mediaController.playbackState).thenReturn(playingState)
val mediaPlaying = mediaData.copy(isPlaying = true)
- mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaPlaying)
+ loadMediaData(KEY, null, mediaPlaying)
// THEN the timeout runnable will update the state
- assertThat(executor.numPending()).isEqualTo(1)
- with(executor) {
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
+ with(mainExecutor) {
advanceClockToNext()
runAllReady()
}
@@ -322,31 +330,32 @@
fun testOnSessionDestroyed_resume_continuesTimeout() {
// GIVEN resume media with session info
val resumeWithSession = resumeData.copy(token = session.sessionToken)
- mediaTimeoutListener.onMediaDataLoaded(PACKAGE, null, resumeWithSession)
+ loadMediaData(PACKAGE, null, resumeWithSession)
verify(mediaController).registerCallback(capture(mediaCallbackCaptor))
- assertThat(executor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
// WHEN the session is destroyed
mediaCallbackCaptor.value.onSessionDestroyed()
// THEN the controller is unregistered, but the timeout is still scheduled
+ assertThat(bgExecutor.runAllReady()).isEqualTo(1)
verify(mediaController).unregisterCallback(anyObject())
- assertThat(executor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
verify(sessionCallback, never()).invoke(eq(KEY))
}
@Test
fun testOnMediaDataLoaded_activeToResume_registersTimeout() {
// WHEN a regular media is loaded
- mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+ loadMediaData(KEY, null, mediaData)
// AND it turns into a resume control
- mediaTimeoutListener.onMediaDataLoaded(PACKAGE, KEY, resumeData)
+ loadMediaData(PACKAGE, KEY, resumeData)
// THEN we register a timeout
- assertThat(executor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
verify(timeoutCallback, never()).invoke(anyString(), anyBoolean())
- assertThat(executor.advanceClockToNext()).isEqualTo(RESUME_MEDIA_TIMEOUT)
+ assertThat(mainExecutor.advanceClockToNext()).isEqualTo(RESUME_MEDIA_TIMEOUT)
}
@Test
@@ -355,42 +364,42 @@
val pausedState =
PlaybackState.Builder().setState(PlaybackState.STATE_PAUSED, 0L, 0f).build()
whenever(mediaController.playbackState).thenReturn(pausedState)
- mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
- assertThat(executor.numPending()).isEqualTo(1)
+ loadMediaData(KEY, null, mediaData)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
// AND it turns into a resume control
- mediaTimeoutListener.onMediaDataLoaded(PACKAGE, KEY, resumeData)
+ loadMediaData(PACKAGE, KEY, resumeData)
// THEN we update the timeout length
- assertThat(executor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
verify(timeoutCallback, never()).invoke(anyString(), anyBoolean())
- assertThat(executor.advanceClockToNext()).isEqualTo(RESUME_MEDIA_TIMEOUT)
+ assertThat(mainExecutor.advanceClockToNext()).isEqualTo(RESUME_MEDIA_TIMEOUT)
}
@Test
fun testOnMediaDataLoaded_resumption_registersTimeout() {
// WHEN a resume media is loaded
- mediaTimeoutListener.onMediaDataLoaded(PACKAGE, null, resumeData)
+ loadMediaData(PACKAGE, null, resumeData)
// THEN we register a timeout
- assertThat(executor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
verify(timeoutCallback, never()).invoke(anyString(), anyBoolean())
- assertThat(executor.advanceClockToNext()).isEqualTo(RESUME_MEDIA_TIMEOUT)
+ assertThat(mainExecutor.advanceClockToNext()).isEqualTo(RESUME_MEDIA_TIMEOUT)
}
@Test
fun testOnMediaDataLoaded_resumeToActive_updatesTimeout() {
// WHEN we have a resume control
- mediaTimeoutListener.onMediaDataLoaded(PACKAGE, null, resumeData)
+ loadMediaData(PACKAGE, null, resumeData)
// AND that media is resumed
val playingState =
PlaybackState.Builder().setState(PlaybackState.STATE_PAUSED, 0L, 0f).build()
whenever(mediaController.playbackState).thenReturn(playingState)
- mediaTimeoutListener.onMediaDataLoaded(KEY, PACKAGE, mediaData)
+ loadMediaData(oldKey = PACKAGE, data = mediaData)
// THEN the timeout length is changed to a regular media control
- assertThat(executor.advanceClockToNext()).isEqualTo(PAUSED_MEDIA_TIMEOUT)
+ assertThat(mainExecutor.advanceClockToNext()).isEqualTo(PAUSED_MEDIA_TIMEOUT)
}
@Test
@@ -401,7 +410,7 @@
mediaTimeoutListener.onMediaDataRemoved(PACKAGE, false)
// THEN the timeout runnable is cancelled
- assertThat(executor.numPending()).isEqualTo(0)
+ assertThat(mainExecutor.numPending()).isEqualTo(0)
}
@Test
@@ -427,6 +436,7 @@
// When the playback state changes, and has different actions
val playingState = PlaybackState.Builder().setActions(PlaybackState.ACTION_PLAY).build()
mediaCallbackCaptor.value.onPlaybackStateChanged(playingState)
+ assertThat(uiExecutor.runAllReady()).isEqualTo(1)
// Then the callback is invoked
verify(stateCallback).invoke(eq(KEY), eq(playingState!!))
@@ -463,6 +473,7 @@
.addCustomAction(customTwo)
.build()
mediaCallbackCaptor.value.onPlaybackStateChanged(pausedStateTwoActions)
+ assertThat(uiExecutor.runAllReady()).isEqualTo(1)
// Then the callback is invoked
verify(stateCallback).invoke(eq(KEY), eq(pausedStateTwoActions!!))
@@ -534,6 +545,7 @@
val playingState =
PlaybackState.Builder().setState(PlaybackState.STATE_PLAYING, 0L, 1f).build()
mediaCallbackCaptor.value.onPlaybackStateChanged(playingState)
+ uiExecutor.runAllReady()
// Then the callback is invoked
verify(stateCallback).invoke(eq(KEY), eq(playingState!!))
@@ -567,7 +579,7 @@
// And we doze past the scheduled timeout
val time = clock.currentTimeMillis()
clock.setElapsedRealtime(time + PAUSED_MEDIA_TIMEOUT)
- assertThat(executor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
// Then when no longer dozing, the timeout runs immediately
dozingCallbackCaptor.value.onDozingChanged(false)
@@ -576,7 +588,7 @@
// and cancel any later scheduled timeout
verify(logger).logTimeoutCancelled(eq(KEY), any())
- assertThat(executor.numPending()).isEqualTo(0)
+ assertThat(mainExecutor.numPending()).isEqualTo(0)
}
@Test
@@ -592,12 +604,12 @@
// And we doze, but not past the scheduled timeout
clock.setElapsedRealtime(time + PAUSED_MEDIA_TIMEOUT / 2L)
- assertThat(executor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
// Then when no longer dozing, the timeout remains scheduled
dozingCallbackCaptor.value.onDozingChanged(false)
verify(timeoutCallback, never()).invoke(eq(KEY), eq(true))
- assertThat(executor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
}
@Test
@@ -610,8 +622,8 @@
whenever(smartspaceData.expiryTimeMs).thenReturn(expireTime)
mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
- assertThat(executor.numPending()).isEqualTo(1)
- assertThat(executor.advanceClockToNext()).isEqualTo(duration)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.advanceClockToNext()).isEqualTo(duration)
}
@Test
@@ -619,7 +631,7 @@
// Given a pending timeout
testSmartspaceDataLoaded_schedulesTimeout()
- executor.runAllReady()
+ mainExecutor.runAllReady()
verify(timeoutCallback).invoke(eq(SMARTSPACE_KEY), eq(true))
}
@@ -634,14 +646,14 @@
whenever(smartspaceData.expiryTimeMs).thenReturn(expireTime)
mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
- assertThat(executor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
val expiryLonger = expireTime + duration
whenever(smartspaceData.expiryTimeMs).thenReturn(expiryLonger)
mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
- assertThat(executor.numPending()).isEqualTo(1)
- assertThat(executor.advanceClockToNext()).isEqualTo(duration * 2)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.advanceClockToNext()).isEqualTo(duration * 2)
}
@Test
@@ -649,10 +661,10 @@
whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
- assertThat(executor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
mediaTimeoutListener.onSmartspaceMediaDataRemoved(SMARTSPACE_KEY)
- assertThat(executor.numPending()).isEqualTo(0)
+ assertThat(mainExecutor.numPending()).isEqualTo(0)
}
@Test
@@ -667,12 +679,12 @@
whenever(smartspaceData.expiryTimeMs).thenReturn(expireTime)
mediaTimeoutListener.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
- assertThat(executor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
// And we doze past the scheduled timeout
val time = clock.currentTimeMillis()
clock.setElapsedRealtime(time + duration * 2)
- assertThat(executor.numPending()).isEqualTo(1)
+ assertThat(mainExecutor.numPending()).isEqualTo(1)
// Then when no longer dozing, the timeout runs immediately
dozingCallbackCaptor.value.onDozingChanged(false)
@@ -680,12 +692,18 @@
verify(logger).logTimeout(eq(SMARTSPACE_KEY))
// and cancel any later scheduled timeout
- assertThat(executor.numPending()).isEqualTo(0)
+ assertThat(mainExecutor.numPending()).isEqualTo(0)
}
private fun loadMediaDataWithPlaybackState(state: PlaybackState) {
whenever(mediaController.playbackState).thenReturn(state)
- mediaTimeoutListener.onMediaDataLoaded(KEY, null, mediaData)
+ loadMediaData(data = mediaData)
verify(mediaController).registerCallback(capture(mediaCallbackCaptor))
}
+
+ private fun loadMediaData(key: String = KEY, oldKey: String? = null, data: MediaData) {
+ mediaTimeoutListener.onMediaDataLoaded(key, oldKey, data)
+ bgExecutor.runAllReady()
+ uiExecutor.runAllReady()
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt
index 1260a65..68a5d93 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt
@@ -79,6 +79,7 @@
import com.android.systemui.media.controls.shared.model.MediaButton
import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.media.controls.shared.model.MediaDeviceData
+import com.android.systemui.media.controls.shared.model.MediaNotificationAction
import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
import com.android.systemui.media.controls.ui.binder.SeekBarObserver
import com.android.systemui.media.controls.ui.view.GutsViewHolder
@@ -236,6 +237,19 @@
@Mock private lateinit var recProgressBar3: SeekBar
@Mock private lateinit var globalSettings: GlobalSettings
+ private val intent =
+ Intent().apply {
+ putExtras(Bundle().also { it.putString(KEY_SMARTSPACE_APP_NAME, REC_APP_NAME) })
+ setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ }
+ private val pendingIntent =
+ PendingIntent.getActivity(
+ mContext,
+ 0,
+ intent.setPackage(mContext.packageName),
+ PendingIntent.FLAG_MUTABLE
+ )
+
@JvmField @Rule val mockito = MockitoJUnit.rule()
@Before
@@ -989,14 +1003,13 @@
@Test
fun bindNotificationActions() {
val icon = context.getDrawable(android.R.drawable.ic_media_play)
- val bg = context.getDrawable(R.drawable.qs_media_round_button_background)
val actions =
listOf(
- MediaAction(icon, Runnable {}, "previous", bg),
- MediaAction(icon, Runnable {}, "play", bg),
- MediaAction(icon, null, "next", bg),
- MediaAction(icon, null, "custom 0", bg),
- MediaAction(icon, Runnable {}, "custom 1", bg)
+ MediaNotificationAction(true, actionIntent = pendingIntent, icon, "previous"),
+ MediaNotificationAction(true, actionIntent = pendingIntent, icon, "play"),
+ MediaNotificationAction(true, actionIntent = null, icon, "next"),
+ MediaNotificationAction(true, actionIntent = null, icon, "custom 0"),
+ MediaNotificationAction(true, actionIntent = pendingIntent, icon, "custom 1")
)
val state =
mediaData.copy(
@@ -1684,11 +1697,11 @@
fun actionCustom2Click_isLogged() {
val actions =
listOf(
- MediaAction(null, Runnable {}, "action 0", null),
- MediaAction(null, Runnable {}, "action 1", null),
- MediaAction(null, Runnable {}, "action 2", null),
- MediaAction(null, Runnable {}, "action 3", null),
- MediaAction(null, Runnable {}, "action 4", null)
+ MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 0"),
+ MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 1"),
+ MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 2"),
+ MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 3"),
+ MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 4")
)
val data = mediaData.copy(actions = actions)
@@ -1703,11 +1716,11 @@
fun actionCustom3Click_isLogged() {
val actions =
listOf(
- MediaAction(null, Runnable {}, "action 0", null),
- MediaAction(null, Runnable {}, "action 1", null),
- MediaAction(null, Runnable {}, "action 2", null),
- MediaAction(null, Runnable {}, "action 3", null),
- MediaAction(null, Runnable {}, "action 4", null)
+ MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 0"),
+ MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 1"),
+ MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 2"),
+ MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 3"),
+ MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 4")
)
val data = mediaData.copy(actions = actions)
@@ -1722,11 +1735,11 @@
fun actionCustom4Click_isLogged() {
val actions =
listOf(
- MediaAction(null, Runnable {}, "action 0", null),
- MediaAction(null, Runnable {}, "action 1", null),
- MediaAction(null, Runnable {}, "action 2", null),
- MediaAction(null, Runnable {}, "action 3", null),
- MediaAction(null, Runnable {}, "action 4", null)
+ MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 0"),
+ MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 1"),
+ MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 2"),
+ MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 3"),
+ MediaNotificationAction(true, actionIntent = pendingIntent, null, "action 4")
)
val data = mediaData.copy(actions = actions)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
index c1cf91d..bc0ec2d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
@@ -22,6 +22,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.systemui.Flags.FLAG_QS_CUSTOM_TILE_CLICK_GUARANTEED_BUG_FIX;
+import static com.android.systemui.Flags.FLAG_QS_QUICK_REBIND_ACTIVE_TILES;
import static com.google.common.truth.Truth.assertThat;
@@ -75,6 +76,8 @@
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
+import com.google.common.truth.Truth;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -95,7 +98,8 @@
@Parameters(name = "{0}")
public static List<FlagsParameterization> getParams() {
- return allCombinationsOf(FLAG_QS_CUSTOM_TILE_CLICK_GUARANTEED_BUG_FIX);
+ return allCombinationsOf(FLAG_QS_CUSTOM_TILE_CLICK_GUARANTEED_BUG_FIX,
+ FLAG_QS_QUICK_REBIND_ACTIVE_TILES);
}
private final PackageManagerAdapter mMockPackageManagerAdapter =
@@ -154,7 +158,8 @@
mUser,
mActivityManager,
mDeviceIdleController,
- mExecutor);
+ mExecutor,
+ mClock);
}
@After
@@ -169,12 +174,12 @@
mStateManager.handleDestroy();
}
- private void setPackageEnabled(boolean enabled) throws Exception {
+ private void setPackageEnabledAndActive(boolean enabled, boolean active) throws Exception {
ServiceInfo defaultServiceInfo = null;
if (enabled) {
defaultServiceInfo = new ServiceInfo();
defaultServiceInfo.metaData = new Bundle();
- defaultServiceInfo.metaData.putBoolean(TileService.META_DATA_ACTIVE_TILE, true);
+ defaultServiceInfo.metaData.putBoolean(TileService.META_DATA_ACTIVE_TILE, active);
defaultServiceInfo.metaData.putBoolean(TileService.META_DATA_TOGGLEABLE_TILE, true);
}
when(mMockPackageManagerAdapter.getServiceInfo(any(), anyInt(), anyInt()))
@@ -186,6 +191,10 @@
.thenReturn(defaultPackageInfo);
}
+ private void setPackageEnabled(boolean enabled) throws Exception {
+ setPackageEnabledAndActive(enabled, true);
+ }
+
private void setPackageInstalledForUser(
boolean installed,
boolean active,
@@ -396,13 +405,40 @@
}
@Test
- public void testKillProcess() throws Exception {
+ public void testKillProcessWhenTileServiceIsNotActive() throws Exception {
+ setPackageEnabledAndActive(true, false);
mStateManager.onStartListening();
mStateManager.executeSetBindService(true);
mExecutor.runAllReady();
+ verifyBind(1);
+ verify(mMockTileService, times(1)).onStartListening();
+
mStateManager.onBindingDied(mTileServiceComponentName);
mExecutor.runAllReady();
- mClock.advanceTime(5000);
+ mClock.advanceTime(1000);
+ mExecutor.runAllReady();
+
+ // still 4 seconds left because non active tile service rebind time is 5 seconds
+ Truth.assertThat(mContext.isBound(mTileServiceComponentName)).isFalse();
+
+ mClock.advanceTime(4000); // 5 seconds delay for nonActive service rebinding
+ mExecutor.runAllReady();
+ verifyBind(2);
+ verify(mMockTileService, times(2)).onStartListening();
+ }
+
+ @EnableFlags(FLAG_QS_QUICK_REBIND_ACTIVE_TILES)
+ @Test
+ public void testKillProcessWhenTileServiceIsActive_withRebindFlagOn() throws Exception {
+ mStateManager.onStartListening();
+ mStateManager.executeSetBindService(true);
+ mExecutor.runAllReady();
+ verifyBind(1);
+ verify(mMockTileService, times(1)).onStartListening();
+
+ mStateManager.onBindingDied(mTileServiceComponentName);
+ mExecutor.runAllReady();
+ mClock.advanceTime(1000);
mExecutor.runAllReady();
// Two calls: one for the first bind, one for the restart.
@@ -410,6 +446,86 @@
verify(mMockTileService, times(2)).onStartListening();
}
+ @DisableFlags(FLAG_QS_QUICK_REBIND_ACTIVE_TILES)
+ @Test
+ public void testKillProcessWhenTileServiceIsActive_withRebindFlagOff() throws Exception {
+ mStateManager.onStartListening();
+ mStateManager.executeSetBindService(true);
+ mExecutor.runAllReady();
+ verifyBind(1);
+ verify(mMockTileService, times(1)).onStartListening();
+
+ mStateManager.onBindingDied(mTileServiceComponentName);
+ mExecutor.runAllReady();
+ mClock.advanceTime(1000);
+ mExecutor.runAllReady();
+ verifyBind(0); // the rebind happens after 4 more seconds
+
+ mClock.advanceTime(4000);
+ mExecutor.runAllReady();
+ verifyBind(1);
+ }
+
+ @EnableFlags(FLAG_QS_QUICK_REBIND_ACTIVE_TILES)
+ @Test
+ public void testKillProcessWhenTileServiceIsActiveTwice_withRebindFlagOn_delaysSecondRebind()
+ throws Exception {
+ mStateManager.onStartListening();
+ mStateManager.executeSetBindService(true);
+ mExecutor.runAllReady();
+ verifyBind(1);
+ verify(mMockTileService, times(1)).onStartListening();
+
+ mStateManager.onBindingDied(mTileServiceComponentName);
+ mExecutor.runAllReady();
+ mClock.advanceTime(1000);
+ mExecutor.runAllReady();
+
+ // Two calls: one for the first bind, one for the restart.
+ verifyBind(2);
+ verify(mMockTileService, times(2)).onStartListening();
+
+ mStateManager.onBindingDied(mTileServiceComponentName);
+ mExecutor.runAllReady();
+ mClock.advanceTime(1000);
+ mExecutor.runAllReady();
+ // because active tile will take 5 seconds to bind the second time, not 1
+ verifyBind(0);
+
+ mClock.advanceTime(4000);
+ mExecutor.runAllReady();
+ verifyBind(1);
+ }
+
+ @DisableFlags(FLAG_QS_QUICK_REBIND_ACTIVE_TILES)
+ @Test
+ public void testKillProcessWhenTileServiceIsActiveTwice_withRebindFlagOff_rebindsFromFirstKill()
+ throws Exception {
+ mStateManager.onStartListening();
+ mStateManager.executeSetBindService(true);
+ mExecutor.runAllReady();
+ verifyBind(1);
+ verify(mMockTileService, times(1)).onStartListening();
+
+ mStateManager.onBindingDied(mTileServiceComponentName); // rebind scheduled for 5 seconds
+ mExecutor.runAllReady();
+ mClock.advanceTime(1000);
+ mExecutor.runAllReady();
+
+ verifyBind(0); // it would bind in 4 more seconds
+
+ mStateManager.onBindingDied(mTileServiceComponentName); // this does not affect the rebind
+ mExecutor.runAllReady();
+ mClock.advanceTime(1000);
+ mExecutor.runAllReady();
+
+ verifyBind(0); // only 2 seconds passed from first kill
+
+ mClock.advanceTime(3000);
+ mExecutor.runAllReady();
+ verifyBind(1); // the rebind scheduled 5 seconds from the first kill should now happen
+ }
+
@Test
public void testKillProcessLowMemory() throws Exception {
doAnswer(invocation -> {
@@ -510,7 +626,8 @@
mUser,
mActivityManager,
mDeviceIdleController,
- mExecutor);
+ mExecutor,
+ mClock);
manager.executeSetBindService(true);
mExecutor.runAllReady();
@@ -533,7 +650,8 @@
mUser,
mActivityManager,
mDeviceIdleController,
- mExecutor);
+ mExecutor,
+ mClock);
manager.executeSetBindService(true);
mExecutor.runAllReady();
@@ -556,7 +674,8 @@
mUser,
mActivityManager,
mDeviceIdleController,
- mExecutor);
+ mExecutor,
+ mClock);
manager.executeSetBindService(true);
mExecutor.runAllReady();
@@ -581,7 +700,8 @@
mUser,
mActivityManager,
mDeviceIdleController,
- mExecutor);
+ mExecutor,
+ mClock);
manager.executeSetBindService(true);
mExecutor.runAllReady();
@@ -607,7 +727,8 @@
mUser,
mActivityManager,
mDeviceIdleController,
- mExecutor);
+ mExecutor,
+ mClock);
assertThat(manager.isActiveTile()).isTrue();
}
@@ -626,7 +747,8 @@
mUser,
mActivityManager,
mDeviceIdleController,
- mExecutor);
+ mExecutor,
+ mClock);
assertThat(manager.isActiveTile()).isTrue();
}
@@ -644,7 +766,8 @@
mUser,
mActivityManager,
mDeviceIdleController,
- mExecutor);
+ mExecutor,
+ mClock);
assertThat(manager.isToggleableTile()).isTrue();
}
@@ -663,7 +786,8 @@
mUser,
mActivityManager,
mDeviceIdleController,
- mExecutor);
+ mExecutor,
+ mClock);
assertThat(manager.isToggleableTile()).isTrue();
}
@@ -682,7 +806,8 @@
mUser,
mActivityManager,
mDeviceIdleController,
- mExecutor);
+ mExecutor,
+ mClock);
assertThat(manager.isToggleableTile()).isFalse();
assertThat(manager.isActiveTile()).isFalse();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java
index 76c8cf0..7d41a20 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.qs.tiles;
+import static com.android.systemui.accessibility.hearingaid.HearingDevicesUiEventLogger.LAUNCH_SOURCE_QS_TILE;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -151,7 +153,7 @@
mTile.handleClick(expandable);
mTestableLooper.processAllMessages();
- verify(mHearingDevicesDialogManager).showDialog(expandable);
+ verify(mHearingDevicesDialogManager).showDialog(expandable, LAUNCH_SOURCE_QS_TILE);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt
index 828c7b2..e6ec07e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/InternetTileNewImplTest.kt
@@ -259,7 +259,6 @@
const val WIFI_SSID = "test ssid"
val ACTIVE_WIFI =
WifiNetworkModel.Active(
- networkId = 1,
isValidated = true,
level = 4,
ssid = WIFI_SSID,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RecordIssueTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RecordIssueTileTest.kt
index 73548ba..ca518f9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RecordIssueTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RecordIssueTileTest.kt
@@ -35,6 +35,7 @@
import com.android.systemui.recordissue.RecordIssueDialogDelegate
import com.android.systemui.recordissue.TraceurMessageSender
import com.android.systemui.res.R
+import com.android.systemui.screenrecord.RecordingController
import com.android.systemui.settings.UserContextProvider
import com.android.systemui.statusbar.phone.KeyguardDismissUtil
import com.android.systemui.statusbar.phone.SystemUIDialog
@@ -65,6 +66,7 @@
@Mock private lateinit var qsEventLogger: QsEventLogger
@Mock private lateinit var metricsLogger: MetricsLogger
@Mock private lateinit var statusBarStateController: StatusBarStateController
+ @Mock private lateinit var recordingController: RecordingController
@Mock private lateinit var activityStarter: ActivityStarter
@Mock private lateinit var qsLogger: QSLogger
@Mock private lateinit var keyguardDismissUtil: KeyguardDismissUtil
@@ -109,6 +111,7 @@
Executors.newSingleThreadExecutor(),
issueRecordingState,
delegateFactory,
+ recordingController,
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recordissue/IssueRecordingServiceCommandHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recordissue/IssueRecordingServiceCommandHandlerTest.kt
new file mode 100644
index 0000000..57cfe1b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/recordissue/IssueRecordingServiceCommandHandlerTest.kt
@@ -0,0 +1,139 @@
+/*
+ * 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.recordissue
+
+import android.app.IActivityManager
+import android.app.NotificationManager
+import android.net.Uri
+import android.os.UserHandle
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.animation.dialogTransitionAnimator
+import com.android.systemui.concurrency.fakeExecutor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testCase
+import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor
+import com.android.systemui.settings.UserContextProvider
+import com.android.systemui.settings.userFileManager
+import com.android.systemui.settings.userTracker
+import com.android.traceur.TraceConfig
+import com.google.common.truth.Truth
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.kotlin.any
+import org.mockito.kotlin.isNull
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class IssueRecordingServiceCommandHandlerTest : SysuiTestCase() {
+
+ private val kosmos = Kosmos().also { it.testCase = this }
+ private val bgExecutor = kosmos.fakeExecutor
+ private val userContextProvider: UserContextProvider = kosmos.userTracker
+ private val dialogTransitionAnimator: DialogTransitionAnimator = kosmos.dialogTransitionAnimator
+ private lateinit var traceurMessageSender: TraceurMessageSender
+ private val issueRecordingState =
+ IssueRecordingState(kosmos.userTracker, kosmos.userFileManager)
+
+ private val iActivityManager = mock<IActivityManager>()
+ private val notificationManager = mock<NotificationManager>()
+ private val panelInteractor = mock<PanelInteractor>()
+
+ private lateinit var underTest: IssueRecordingServiceCommandHandler
+
+ @Before
+ fun setup() {
+ traceurMessageSender = mock<TraceurMessageSender>()
+ underTest =
+ IssueRecordingServiceCommandHandler(
+ bgExecutor,
+ dialogTransitionAnimator,
+ panelInteractor,
+ traceurMessageSender,
+ issueRecordingState,
+ iActivityManager,
+ notificationManager,
+ userContextProvider
+ )
+ }
+
+ @Test
+ fun startsTracing_afterReceivingActionStartCommand() {
+ underTest.handleStartCommand()
+ bgExecutor.runAllReady()
+
+ Truth.assertThat(issueRecordingState.isRecording).isTrue()
+ verify(traceurMessageSender).startTracing(any<TraceConfig>())
+ }
+
+ @Test
+ fun stopsTracing_afterReceivingStopTracingCommand() {
+ underTest.handleStopCommand(mContext.contentResolver)
+ bgExecutor.runAllReady()
+
+ Truth.assertThat(issueRecordingState.isRecording).isFalse()
+ verify(traceurMessageSender).stopTracing()
+ }
+
+ @Test
+ fun cancelsNotification_afterReceivingShareCommand() {
+ underTest.handleShareCommand(0, null, mContext)
+ bgExecutor.runAllReady()
+
+ verify(notificationManager).cancelAsUser(isNull(), anyInt(), any<UserHandle>())
+ }
+
+ @Test
+ fun requestBugreport_afterReceivingShareCommand_withTakeBugreportTrue() {
+ issueRecordingState.takeBugreport = true
+ val uri = mock<Uri>()
+
+ underTest.handleShareCommand(0, uri, mContext)
+ bgExecutor.runAllReady()
+
+ verify(iActivityManager).requestBugReportWithExtraAttachment(uri)
+ }
+
+ @Test
+ fun sharesTracesDirectly_afterReceivingShareCommand_withTakeBugreportFalse() {
+ issueRecordingState.takeBugreport = false
+ val uri = mock<Uri>()
+
+ underTest.handleShareCommand(0, uri, mContext)
+ bgExecutor.runAllReady()
+
+ verify(traceurMessageSender).shareTraces(mContext, uri)
+ }
+
+ @Test
+ fun closesShade_afterReceivingShareCommand() {
+ val uri = mock<Uri>()
+
+ underTest.handleShareCommand(0, uri, mContext)
+ bgExecutor.runAllReady()
+
+ verify(panelInteractor).collapsePanels()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recordissue/IssueRecordingStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recordissue/IssueRecordingStateTest.kt
new file mode 100644
index 0000000..4ab3c7b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/recordissue/IssueRecordingStateTest.kt
@@ -0,0 +1,109 @@
+/*
+ * 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.recordissue
+
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.settings.userFileManager
+import com.android.systemui.settings.userTracker
+import com.google.common.truth.Truth
+import java.util.concurrent.CountDownLatch
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class IssueRecordingStateTest : SysuiTestCase() {
+
+ private val kosmos = Kosmos()
+ private lateinit var underTest: IssueRecordingState
+
+ @Before
+ fun setup() {
+ underTest = IssueRecordingState(kosmos.userTracker, kosmos.userFileManager)
+ }
+
+ @Test
+ fun takeBugreport_isSaved_betweenDifferentSessions() {
+ val expected = true
+
+ underTest.takeBugreport = expected
+ underTest = IssueRecordingState(kosmos.userTracker, kosmos.userFileManager)
+
+ Truth.assertThat(underTest.takeBugreport).isEqualTo(expected)
+ }
+
+ @Test
+ fun recordScreen_isSaved_betweenDifferentSessions() {
+ val expected = true
+
+ underTest.recordScreen = expected
+ underTest = IssueRecordingState(kosmos.userTracker, kosmos.userFileManager)
+
+ Truth.assertThat(underTest.recordScreen).isEqualTo(expected)
+ }
+
+ @Test
+ fun hasUserApprovedScreenRecording_isTrue_afterBeingMarkedAsCompleted() {
+ underTest.markUserApprovalForScreenRecording()
+ underTest = IssueRecordingState(kosmos.userTracker, kosmos.userFileManager)
+
+ Truth.assertThat(underTest.hasUserApprovedScreenRecording).isEqualTo(true)
+ }
+
+ @Test
+ fun tagTitles_areSavedConsistently() {
+ val expected = setOf("a", "b", "c")
+
+ underTest.tagTitles = expected
+ underTest = IssueRecordingState(kosmos.userTracker, kosmos.userFileManager)
+
+ Truth.assertThat(underTest.tagTitles).isEqualTo(expected)
+ }
+
+ @Test
+ fun isRecording_callsListeners_onTheValueChanging() {
+ val count = CountDownLatch(1)
+ val listener = Runnable { count.countDown() }
+
+ underTest.addListener(listener)
+ underTest.isRecording = true
+
+ Truth.assertThat(count.count).isEqualTo(0)
+ }
+
+ @Test
+ fun isRecording_callsOnlyListeners_whoHaveNotBeenRemoved() {
+ val count1 = CountDownLatch(1)
+ val count2 = CountDownLatch(1)
+ val listener1 = Runnable { count1.countDown() }
+ val listener2 = Runnable { count2.countDown() }
+
+ underTest.addListener(listener1)
+ underTest.removeListener(listener1)
+ underTest.addListener(listener2)
+ underTest.isRecording = true
+
+ Truth.assertThat(count1.count).isEqualTo(1)
+ Truth.assertThat(count2.count).isEqualTo(0)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java
index eb1a04d..e1cd5e4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java
@@ -30,12 +30,15 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
import android.app.IActivityTaskManager;
import android.app.assist.AssistContent;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -51,6 +54,7 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
+import android.os.UserHandle;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.testing.AndroidTestingRunner;
@@ -120,6 +124,8 @@
@Mock
private AssistContentRequester mAssistContentRequester;
@Mock
+ private Context mMockedContext;
+ @Mock
private PackageManager mPackageManager;
@Mock
private UserTracker mUserTracker;
@@ -127,6 +133,9 @@
private UiEventLogger mUiEventLogger;
private AppClipsActivity mActivity;
+ private TextView mBacklinksDataTextView;
+ private CheckBox mBacklinksIncludeDataCheckBox;
+ private TextView mBacklinksCrossProfileErrorTextView;
// Using the deprecated ActivityTestRule and SingleActivityFactory to help with injecting mocks.
private final SingleActivityFactory<AppClipsActivityTestable> mFactory =
@@ -136,7 +145,7 @@
return new AppClipsActivityTestable(
new AppClipsViewModel.Factory(mAppClipsCrossProcessHelper,
mImageExporter, mAtmService, mAssistContentRequester,
- mPackageManager, getContext().getMainExecutor(),
+ mMockedContext, getContext().getMainExecutor(),
directExecutor()),
mPackageManager, mUserTracker, mUiEventLogger);
}
@@ -162,6 +171,9 @@
when(mImageExporter.export(any(Executor.class), any(UUID.class), any(Bitmap.class),
eq(Process.myUserHandle()), eq(Display.DEFAULT_DISPLAY)))
.thenReturn(Futures.immediateFuture(result));
+
+ when(mMockedContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mMockedContext.createContextAsUser(any(), anyInt())).thenReturn(mMockedContext);
}
@After
@@ -175,10 +187,9 @@
launchActivity();
assertThat(((ImageView) mActivity.findViewById(R.id.preview)).getDrawable()).isNotNull();
- assertThat(mActivity.findViewById(R.id.backlinks_data).getVisibility())
- .isEqualTo(View.GONE);
- assertThat(mActivity.findViewById(R.id.backlinks_include_data).getVisibility())
- .isEqualTo(View.GONE);
+ assertThat(mBacklinksDataTextView.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mBacklinksIncludeDataCheckBox.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mBacklinksCrossProfileErrorTextView.getVisibility()).isEqualTo(View.GONE);
}
@Test
@@ -228,20 +239,23 @@
waitForIdleSync();
assertThat(mDisplayIdCaptor.getValue()).isEqualTo(mActivity.getDisplayId());
- TextView backlinksData = mActivity.findViewById(R.id.backlinks_data);
- assertThat(backlinksData.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(backlinksData.getText().toString()).isEqualTo(BACKLINKS_TASK_APP_NAME);
- assertThat(backlinksData.getCompoundDrawablesRelative()[0]).isEqualTo(FAKE_DRAWABLE);
+ assertThat(mBacklinksDataTextView.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mBacklinksDataTextView.getText().toString()).isEqualTo(BACKLINKS_TASK_APP_NAME);
+ assertThat(mBacklinksDataTextView.getCompoundDrawablesRelative()[0])
+ .isEqualTo(FAKE_DRAWABLE);
// Verify dropdown icon is not shown and there are no click listeners on text view.
- assertThat(backlinksData.getCompoundDrawablesRelative()[2]).isNull();
- assertThat(backlinksData.hasOnClickListeners()).isFalse();
+ assertThat(mBacklinksDataTextView.getCompoundDrawablesRelative()[2]).isNull();
+ assertThat(mBacklinksDataTextView.hasOnClickListeners()).isFalse();
- CheckBox backlinksIncludeData = mActivity.findViewById(R.id.backlinks_include_data);
- assertThat(backlinksIncludeData.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(backlinksIncludeData.getText().toString())
+ assertThat(mBacklinksIncludeDataCheckBox.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mBacklinksIncludeDataCheckBox.getText().toString())
.isEqualTo(mActivity.getString(R.string.backlinks_include_link));
- assertThat(backlinksIncludeData.isChecked()).isTrue();
+ assertThat(mBacklinksIncludeDataCheckBox.isChecked()).isTrue();
+
+ assertThat(mBacklinksIncludeDataCheckBox.getAlpha()).isEqualTo(1.0f);
+ assertThat(mBacklinksIncludeDataCheckBox.isEnabled()).isTrue();
+ assertThat(mBacklinksCrossProfileErrorTextView.getVisibility()).isEqualTo(View.GONE);
}
@Test
@@ -258,8 +272,7 @@
assertThat(backlinksIncludeData.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(backlinksIncludeData.isChecked()).isFalse();
- TextView backlinksData = mActivity.findViewById(R.id.backlinks_data);
- assertThat(backlinksData.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mBacklinksDataTextView.getVisibility()).isEqualTo(View.GONE);
}
@Test
@@ -300,12 +313,11 @@
waitForIdleSync();
// Verify default backlink shown to user and text view has on click listener.
- TextView backlinksData = mActivity.findViewById(R.id.backlinks_data);
- assertThat(backlinksData.getText().toString()).isEqualTo(BACKLINKS_TASK_APP_NAME);
- assertThat(backlinksData.hasOnClickListeners()).isTrue();
+ assertThat(mBacklinksDataTextView.getText().toString()).isEqualTo(BACKLINKS_TASK_APP_NAME);
+ assertThat(mBacklinksDataTextView.hasOnClickListeners()).isTrue();
// Verify dropdown icon is not null.
- assertThat(backlinksData.getCompoundDrawablesRelative()[2]).isNotNull();
+ assertThat(mBacklinksDataTextView.getCompoundDrawablesRelative()[2]).isNotNull();
}
@Test
@@ -336,12 +348,35 @@
waitForIdleSync();
// Verify default backlink shown to user has the numerical suffix.
- TextView backlinksData = mActivity.findViewById(R.id.backlinks_data);
- assertThat(backlinksData.getText().toString()).isEqualTo(
- mContext.getString(R.string.backlinks_duplicate_label_format,
+ assertThat(mBacklinksDataTextView.getText().toString()).isEqualTo(
+ getContext().getString(R.string.backlinks_duplicate_label_format,
BACKLINKS_TASK_APP_NAME, 1));
}
+ @Test
+ @EnableFlags(Flags.FLAG_APP_CLIPS_BACKLINKS)
+ public void appClipsLaunched_backlinks_singleBacklink_crossProfileError()
+ throws RemoteException {
+ // Set up mocking for cross profile backlink.
+ setUpMocksForBacklinks();
+ ActivityManager.RunningTaskInfo crossProfileTaskInfo = createTaskInfoForBacklinksTask();
+ crossProfileTaskInfo.userId = UserHandle.myUserId() + 1;
+ reset(mAtmService);
+ when(mAtmService.getTasks(eq(Integer.MAX_VALUE), eq(false), eq(false),
+ mDisplayIdCaptor.capture())).thenReturn(List.of(crossProfileTaskInfo));
+
+ // Trigger backlinks.
+ launchActivity();
+ waitForIdleSync();
+
+ // Verify views for cross profile backlinks error.
+ assertThat(mBacklinksIncludeDataCheckBox.getAlpha()).isLessThan(1.0f);
+ assertThat(mBacklinksIncludeDataCheckBox.isEnabled()).isFalse();
+ assertThat(mBacklinksIncludeDataCheckBox.isChecked()).isFalse();
+
+ assertThat(mBacklinksCrossProfileErrorTextView.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
private void setUpMocksForBacklinks() throws RemoteException {
when(mAtmService.getTasks(eq(Integer.MAX_VALUE), eq(false), eq(false),
mDisplayIdCaptor.capture()))
@@ -373,11 +408,15 @@
mActivity = mActivityRule.launchActivity(intent);
waitForIdleSync();
+ mBacklinksDataTextView = mActivity.findViewById(R.id.backlinks_data);
+ mBacklinksIncludeDataCheckBox = mActivity.findViewById(R.id.backlinks_include_data);
+ mBacklinksCrossProfileErrorTextView = mActivity.findViewById(
+ R.id.backlinks_cross_profile_error);
}
private ResultReceiver createResultReceiver(
BiConsumer<Integer, Bundle> resultReceiverConsumer) {
- ResultReceiver testReceiver = new ResultReceiver(mContext.getMainThreadHandler()) {
+ ResultReceiver testReceiver = new ResultReceiver(getContext().getMainThreadHandler()) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
resultReceiverConsumer.accept(resultCode, resultData);
@@ -394,7 +433,7 @@
}
private void runOnMainThread(Runnable runnable) {
- mContext.getMainExecutor().execute(runnable);
+ getContext().getMainExecutor().execute(runnable);
}
private static ResolveInfo createBacklinksTaskResolveInfo() {
@@ -418,6 +457,7 @@
taskInfo.topActivityInfo = createBacklinksTaskResolveInfo().activityInfo;
taskInfo.baseIntent = new Intent().setComponent(taskInfo.topActivity);
taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_STANDARD);
+ taskInfo.userId = UserHandle.myUserId();
return taskInfo;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsViewModelTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsViewModelTest.java
index 178547e..5d71c05 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsViewModelTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsViewModelTest.java
@@ -30,6 +30,7 @@
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
@@ -43,6 +44,7 @@
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -62,6 +64,8 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.screenshot.AssistContentRequester;
import com.android.systemui.screenshot.ImageExporter;
+import com.android.systemui.screenshot.appclips.InternalBacklinksData.BacklinksData;
+import com.android.systemui.screenshot.appclips.InternalBacklinksData.CrossProfileError;
import com.google.common.util.concurrent.Futures;
@@ -92,10 +96,16 @@
private static final String BACKLINKS_TASK_PACKAGE_NAME = "backlinksTaskPackageName";
private static final AssistContent EMPTY_ASSIST_CONTENT = new AssistContent();
- @Mock private AppClipsCrossProcessHelper mAppClipsCrossProcessHelper;
- @Mock private ImageExporter mImageExporter;
- @Mock private IActivityTaskManager mAtmService;
- @Mock private AssistContentRequester mAssistContentRequester;
+ @Mock
+ private AppClipsCrossProcessHelper mAppClipsCrossProcessHelper;
+ @Mock
+ private ImageExporter mImageExporter;
+ @Mock
+ private IActivityTaskManager mAtmService;
+ @Mock
+ private AssistContentRequester mAssistContentRequester;
+ @Mock
+ Context mMockedContext;
@Mock
private PackageManager mPackageManager;
private ArgumentCaptor<Intent> mPackageManagerIntentCaptor;
@@ -112,10 +122,14 @@
when(mPackageManager.resolveActivity(mPackageManagerIntentCaptor.capture(), anyInt()))
.thenReturn(createBacklinksTaskResolveInfo());
when(mPackageManager.loadItemIcon(any(), any())).thenReturn(FAKE_DRAWABLE);
+ when(mMockedContext.getPackageManager()).thenReturn(mPackageManager);
mViewModel = new AppClipsViewModel.Factory(mAppClipsCrossProcessHelper, mImageExporter,
- mAtmService, mAssistContentRequester, mPackageManager,
+ mAtmService, mAssistContentRequester, mMockedContext,
getContext().getMainExecutor(), directExecutor()).create(AppClipsViewModel.class);
+
+ when(mMockedContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mMockedContext.createContextAsUser(any(), anyInt())).thenReturn(mMockedContext);
}
@Test
@@ -199,7 +213,7 @@
assertThat(queriedIntent.getData()).isEqualTo(expectedUri);
assertThat(queriedIntent.getAction()).isEqualTo(ACTION_VIEW);
- InternalBacklinksData result = mViewModel.mSelectedBacklinksLiveData.getValue();
+ BacklinksData result = (BacklinksData) mViewModel.mSelectedBacklinksLiveData.getValue();
assertThat(result.getAppIcon()).isEqualTo(FAKE_DRAWABLE);
ClipData clipData = result.getClipData();
ClipDescription resultDescription = clipData.getDescription();
@@ -238,7 +252,7 @@
Intent queriedIntent = mPackageManagerIntentCaptor.getValue();
assertThat(queriedIntent.getPackage()).isEqualTo(expectedIntent.getPackage());
- InternalBacklinksData result = mViewModel.mSelectedBacklinksLiveData.getValue();
+ BacklinksData result = (BacklinksData) mViewModel.mSelectedBacklinksLiveData.getValue();
assertThat(result.getAppIcon()).isEqualTo(FAKE_DRAWABLE);
ClipData clipData = result.getClipData();
ClipDescription resultDescription = clipData.getDescription();
@@ -307,6 +321,8 @@
@Test
public void triggerBacklinks_taskIdsToIgnoreConsidered_noBacklinkAvailable() {
+ mockForAssistContent(EMPTY_ASSIST_CONTENT, BACKLINKS_TASK_ID);
+
mViewModel.triggerBacklinks(Set.of(BACKLINKS_TASK_ID), DEFAULT_DISPLAY);
waitForIdleSync();
@@ -362,16 +378,58 @@
waitForIdleSync();
// Verify two backlinks are received and the first backlink is set as default selected.
- assertThat(mViewModel.mSelectedBacklinksLiveData.getValue().getClipData().getItemAt(
- 0).getUri()).isEqualTo(expectedUri);
+ assertThat(
+ ((BacklinksData) mViewModel.mSelectedBacklinksLiveData.getValue())
+ .getClipData().getItemAt(0).getUri())
+ .isEqualTo(expectedUri);
List<InternalBacklinksData> actualBacklinks = mViewModel.getBacklinksLiveData().getValue();
assertThat(actualBacklinks).hasSize(2);
- assertThat(actualBacklinks.get(0).getClipData().getItemAt(0).getUri())
+ assertThat(((BacklinksData) actualBacklinks.get(0)).getClipData().getItemAt(0).getUri())
.isEqualTo(expectedUri);
- assertThat(actualBacklinks.get(1).getClipData().getItemAt(0).getIntent())
+ assertThat(((BacklinksData) actualBacklinks.get(1)).getClipData().getItemAt(0).getIntent())
.isEqualTo(expectedIntent);
}
+ @Test
+ public void triggerBacklinks_singleCrossProfileApp_shouldIndicateError()
+ throws RemoteException {
+ reset(mAtmService);
+ RunningTaskInfo taskInfo = createTaskInfoForBacklinksTask();
+ taskInfo.userId = UserHandle.myUserId() + 1;
+ when(mAtmService.getTasks(Integer.MAX_VALUE, false, false, DEFAULT_DISPLAY))
+ .thenReturn(List.of(taskInfo));
+
+ mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY);
+ waitForIdleSync();
+
+ assertThat(mViewModel.mSelectedBacklinksLiveData.getValue())
+ .isInstanceOf(CrossProfileError.class);
+ }
+
+ @Test
+ public void triggerBacklinks_multipleBacklinks_includesCrossProfileError()
+ throws RemoteException {
+ // Set up mocking for multiple backlinks.
+ mockForAssistContent(EMPTY_ASSIST_CONTENT, BACKLINKS_TASK_ID);
+ reset(mAtmService);
+ RunningTaskInfo runningTaskInfo1 = createTaskInfoForBacklinksTask();
+ RunningTaskInfo runningTaskInfo2 = createTaskInfoForBacklinksTask();
+ runningTaskInfo2.userId = UserHandle.myUserId() + 1;
+
+ when(mAtmService.getTasks(anyInt(), anyBoolean(), anyBoolean(), anyInt()))
+ .thenReturn(List.of(runningTaskInfo1, runningTaskInfo2));
+
+ // Set up complete, trigger the backlinks action.
+ mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY);
+ waitForIdleSync();
+
+ // Verify two backlinks are received and only second has error.
+ List<InternalBacklinksData> actualBacklinks = mViewModel.getBacklinksLiveData().getValue();
+ assertThat(actualBacklinks).hasSize(2);
+ assertThat(actualBacklinks.get(0)).isInstanceOf(BacklinksData.class);
+ assertThat(actualBacklinks.get(1)).isInstanceOf(CrossProfileError.class);
+ }
+
private void resetPackageManagerMockingForUsingFallbackBacklinks() {
ResolveInfo backlinksTaskResolveInfo = createBacklinksTaskResolveInfo();
reset(mPackageManager);
@@ -389,7 +447,7 @@
}
private void verifyMainLauncherBacklinksIntent() {
- InternalBacklinksData result = mViewModel.mSelectedBacklinksLiveData.getValue();
+ BacklinksData result = (BacklinksData) mViewModel.mSelectedBacklinksLiveData.getValue();
assertThat(result.getAppIcon()).isEqualTo(FAKE_DRAWABLE);
ClipData clipData = result.getClipData();
@@ -436,6 +494,7 @@
taskInfo.topActivityInfo = createBacklinksTaskResolveInfo().activityInfo;
taskInfo.baseIntent = new Intent().setComponent(taskInfo.topActivity);
taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_STANDARD);
+ taskInfo.userId = UserHandle.myUserId();
return taskInfo;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
index 263b001..78764c2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
@@ -79,21 +79,6 @@
@Test
fun callsCallbackAndUpdatesProfilesWhenAnIntentReceived() = runTest {
- tracker =
- UserTrackerImpl(
- context,
- { fakeFeatures },
- userManager,
- iActivityManager,
- dumpManager,
- this,
- testDispatcher,
- handler
- )
- tracker.initialize(0)
- tracker.addCallback(callback, executor)
- val profileID = tracker.userId + 10
-
`when`(userManager.getProfiles(anyInt())).thenAnswer { invocation ->
val id = invocation.getArgument<Int>(0)
val info = UserInfo(id, "", UserInfo.FLAG_FULL)
@@ -109,6 +94,21 @@
listOf(info, infoProfile)
}
+ tracker =
+ UserTrackerImpl(
+ context,
+ { fakeFeatures },
+ userManager,
+ iActivityManager,
+ dumpManager,
+ this,
+ testDispatcher,
+ handler
+ )
+ tracker.initialize(0)
+ tracker.addCallback(callback, executor)
+ val profileID = tracker.userId + 10
+
tracker.onReceive(context, Intent(intentAction))
verify(callback, times(0)).onUserChanged(anyInt(), any())
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 3ba1447e..c0444fe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
@@ -117,7 +117,8 @@
object : AmbientTouchComponent.Factory {
override fun create(
lifecycleOwner: LifecycleOwner,
- touchHandlers: Set<TouchHandler>
+ touchHandlers: Set<TouchHandler>,
+ loggingName: String
): AmbientTouchComponent =
object : AmbientTouchComponent {
override fun getTouchMonitor(): TouchMonitor = touchMonitor
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/OperatorNameViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/OperatorNameViewControllerTest.kt
index 396d017..d6b3b91 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/OperatorNameViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/OperatorNameViewControllerTest.kt
@@ -28,7 +28,7 @@
import com.android.systemui.plugins.DarkIconDispatcher
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.util.FakeSubscriptionManagerProxy
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
import com.android.systemui.tuner.TunerService
@@ -71,7 +71,6 @@
private val airplaneModeRepository = FakeAirplaneModeRepository()
private val connectivityRepository = FakeConnectivityRepository()
- private val mobileConnectionsRepository = FakeMobileConnectionsRepository()
@Before
fun setup() {
@@ -81,7 +80,7 @@
AirplaneModeInteractor(
airplaneModeRepository,
connectivityRepository,
- mobileConnectionsRepository,
+ kosmos.fakeMobileConnectionsRepository,
)
underTest =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
index a0d231b..60a1855 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
@@ -51,6 +51,7 @@
import android.platform.test.annotations.EnableFlags;
import android.service.notification.StatusBarNotification;
import android.view.ViewGroup;
+import android.widget.ImageView;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -431,6 +432,32 @@
mIconView.getIconScale(), 0.01f);
}
+ @Test
+ @EnableFlags({Flags.FLAG_MODES_UI, Flags.FLAG_MODES_UI_ICONS})
+ public void set_iconThatWantsFixedSpace_setsScaleType() {
+ mIconView.setScaleType(ImageView.ScaleType.FIT_START);
+ StatusBarIcon icon = new StatusBarIcon(UserHandle.ALL, "mockPackage",
+ Icon.createWithResource(mContext, R.drawable.ic_android), 0, 0, "",
+ StatusBarIcon.Type.SystemIcon, StatusBarIcon.Shape.FIXED_SPACE);
+
+ mIconView.set(icon);
+
+ assertThat(mIconView.getScaleType()).isEqualTo(ImageView.ScaleType.FIT_CENTER);
+ }
+
+ @Test
+ @EnableFlags({Flags.FLAG_MODES_UI, Flags.FLAG_MODES_UI_ICONS})
+ public void set_iconWithOtherShape_keepsScaleType() {
+ mIconView.setScaleType(ImageView.ScaleType.FIT_START);
+ StatusBarIcon icon = new StatusBarIcon(UserHandle.ALL, "mockPackage",
+ Icon.createWithResource(mContext, R.drawable.ic_android), 0, 0, "",
+ StatusBarIcon.Type.SystemIcon, StatusBarIcon.Shape.WRAP_CONTENT);
+
+ mIconView.set(icon);
+
+ assertThat(mIconView.getScaleType()).isEqualTo(ImageView.ScaleType.FIT_START);
+ }
+
private static StatusBarNotification getMockSbn() {
StatusBarNotification sbn = mock(StatusBarNotification.class);
when(sbn.getNotification()).thenReturn(mock(Notification.class));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
index bd5df07..f528ebb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
@@ -107,69 +107,69 @@
}
@Test
- fun chip_allHidden_hidden() =
+ fun primaryChip_allHidden_hidden() =
testScope.runTest {
screenRecordState.value = ScreenRecordModel.DoingNothing
mediaProjectionState.value = MediaProjectionState.NotProjecting
callRepo.setOngoingCallState(OngoingCallModel.NoCall)
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Hidden::class.java)
}
@Test
- fun chip_screenRecordShow_restHidden_screenRecordShown() =
+ fun primaryChip_screenRecordShow_restHidden_screenRecordShown() =
testScope.runTest {
screenRecordState.value = ScreenRecordModel.Recording
mediaProjectionState.value = MediaProjectionState.NotProjecting
callRepo.setOngoingCallState(OngoingCallModel.NoCall)
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
assertIsScreenRecordChip(latest)
}
@Test
- fun chip_screenRecordShowAndCallShow_screenRecordShown() =
+ fun primaryChip_screenRecordShowAndCallShow_screenRecordShown() =
testScope.runTest {
screenRecordState.value = ScreenRecordModel.Recording
callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
assertIsScreenRecordChip(latest)
}
@Test
- fun chip_screenRecordShowAndShareToAppShow_screenRecordShown() =
+ fun primaryChip_screenRecordShowAndShareToAppShow_screenRecordShown() =
testScope.runTest {
screenRecordState.value = ScreenRecordModel.Recording
mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
callRepo.setOngoingCallState(OngoingCallModel.NoCall)
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
assertIsScreenRecordChip(latest)
}
@Test
- fun chip_shareToAppShowAndCallShow_shareToAppShown() =
+ fun primaryChip_shareToAppShowAndCallShow_shareToAppShown() =
testScope.runTest {
screenRecordState.value = ScreenRecordModel.DoingNothing
mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
assertIsShareToAppChip(latest)
}
@Test
- fun chip_screenRecordAndShareToAppAndCastToOtherHideAndCallShown_callShown() =
+ fun primaryChip_screenRecordAndShareToAppAndCastToOtherHideAndCallShown_callShown() =
testScope.runTest {
screenRecordState.value = ScreenRecordModel.DoingNothing
// MediaProjection covers both share-to-app and cast-to-other-device
@@ -177,14 +177,14 @@
callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
assertIsCallChip(latest)
}
@Test
@EnableFlags(FLAG_STATUS_BAR_RON_CHIPS)
- fun chip_higherPriorityChipAdded_lowerPriorityChipReplaced() =
+ fun primaryChip_higherPriorityChipAdded_lowerPriorityChipReplaced() =
testScope.runTest {
// Start with just the lowest priority chip shown
addDemoRonChip(commandRegistry, pw)
@@ -193,7 +193,7 @@
mediaProjectionState.value = MediaProjectionState.NotProjecting
screenRecordState.value = ScreenRecordModel.DoingNothing
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
assertIsDemoRonChip(latest)
@@ -223,7 +223,7 @@
@Test
@EnableFlags(FLAG_STATUS_BAR_RON_CHIPS)
- fun chip_highestPriorityChipRemoved_showsNextPriorityChip() =
+ fun primaryChip_highestPriorityChipRemoved_showsNextPriorityChip() =
testScope.runTest {
// WHEN all chips are active
screenRecordState.value = ScreenRecordModel.Recording
@@ -232,7 +232,7 @@
callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
addDemoRonChip(commandRegistry, pw)
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
// THEN the highest priority screen record is used
assertIsScreenRecordChip(latest)
@@ -258,11 +258,11 @@
/** Regression test for b/347726238. */
@Test
- fun chip_timerDoesNotResetAfterSubscribersRestart() =
+ fun primaryChip_timerDoesNotResetAfterSubscribersRestart() =
testScope.runTest {
var latest: OngoingActivityChipModel? = null
- val job1 = underTest.chip.onEach { latest = it }.launchIn(this)
+ val job1 = underTest.primaryChip.onEach { latest = it }.launchIn(this)
// Start a chip with a timer
systemClock.setElapsedRealtime(1234)
@@ -279,7 +279,7 @@
systemClock.setElapsedRealtime(5678)
// WHEN we re-subscribe to the chip flow
- val job2 = underTest.chip.onEach { latest = it }.launchIn(this)
+ val job2 = underTest.primaryChip.onEach { latest = it }.launchIn(this)
runCurrent()
@@ -290,13 +290,13 @@
}
@Test
- fun chip_screenRecordStoppedViaDialog_chipHiddenWithoutAnimation() =
+ fun primaryChip_screenRecordStoppedViaDialog_chipHiddenWithoutAnimation() =
testScope.runTest {
screenRecordState.value = ScreenRecordModel.Recording
mediaProjectionState.value = MediaProjectionState.NotProjecting
callRepo.setOngoingCallState(OngoingCallModel.NoCall)
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
assertIsScreenRecordChip(latest)
@@ -310,14 +310,14 @@
}
@Test
- fun chip_projectionStoppedViaDialog_chipHiddenWithoutAnimation() =
+ fun primaryChip_projectionStoppedViaDialog_chipHiddenWithoutAnimation() =
testScope.runTest {
mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
screenRecordState.value = ScreenRecordModel.DoingNothing
callRepo.setOngoingCallState(OngoingCallModel.NoCall)
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
assertIsShareToAppChip(latest)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index a18de68..a06f4d2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -95,6 +95,8 @@
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.shared.NotificationThrottleHun;
+import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds;
+import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimShape;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -893,7 +895,7 @@
@Test
@DisableFlags({QSComposeFragment.FLAG_NAME, NewQsUI.FLAG_NAME})
- @DisableSceneContainer // TODO(b/312473478): address lack of QS Header
+ @DisableSceneContainer
public void testInsideQSHeader_noOffset() {
ViewGroup qsHeader = mock(ViewGroup.class);
Rect boundsOnScreen = new Rect(0, 0, 1000, 1000);
@@ -911,7 +913,7 @@
@Test
@DisableFlags({QSComposeFragment.FLAG_NAME, NewQsUI.FLAG_NAME})
- @DisableSceneContainer // TODO(b/312473478): address lack of QS Header
+ @DisableSceneContainer
public void testInsideQSHeader_Offset() {
ViewGroup qsHeader = mock(ViewGroup.class);
Rect boundsOnScreen = new Rect(100, 100, 1000, 1000);
@@ -932,7 +934,7 @@
@Test
@EnableFlags({QSComposeFragment.FLAG_NAME, NewQsUI.FLAG_NAME})
- @DisableSceneContainer // TODO(b/312473478): address lack of QS Header
+ @DisableSceneContainer
public void testInsideQSHeader_noOffset_qsCompose() {
ViewGroup qsHeader = mock(ViewGroup.class);
Rect boundsOnScreen = new Rect(0, 0, 1000, 1000);
@@ -959,7 +961,7 @@
@Test
@EnableFlags({QSComposeFragment.FLAG_NAME, NewQsUI.FLAG_NAME})
- @DisableSceneContainer // TODO(b/312473478): address lack of QS Header
+ @DisableSceneContainer
public void testInsideQSHeader_Offset_qsCompose() {
ViewGroup qsHeader = mock(ViewGroup.class);
Rect boundsOnScreen = new Rect(100, 100, 1000, 1000);
@@ -988,6 +990,53 @@
}
@Test
+ @EnableSceneContainer
+ public void testIsInsideScrollableRegion_noScrim() {
+ mStackScroller.setLeftTopRightBottom(0, 0, 2000, 2000);
+
+ MotionEvent event = transformEventForView(createMotionEvent(250f, 250f), mStackScroller);
+ assertThat(mStackScroller.isInScrollableRegion(event)).isTrue();
+ }
+
+ @Test
+ @EnableSceneContainer
+ public void testIsInsideScrollableRegion_noOffset() {
+ mStackScroller.setLeftTopRightBottom(0, 0, 1000, 2000);
+ mStackScroller.setScrimClippingShape(createScrimShape(100, 500, 900, 2000));
+
+ MotionEvent event1 = transformEventForView(createMotionEvent(500f, 400f), mStackScroller);
+ assertThat(mStackScroller.isInScrollableRegion(event1)).isFalse();
+
+ MotionEvent event2 = transformEventForView(createMotionEvent(50, 1000f), mStackScroller);
+ assertThat(mStackScroller.isInScrollableRegion(event2)).isFalse();
+
+ MotionEvent event3 = transformEventForView(createMotionEvent(950f, 1000f), mStackScroller);
+ assertThat(mStackScroller.isInScrollableRegion(event3)).isFalse();
+
+ MotionEvent event4 = transformEventForView(createMotionEvent(500f, 1000f), mStackScroller);
+ assertThat(mStackScroller.isInScrollableRegion(event4)).isTrue();
+ }
+
+ @Test
+ @EnableSceneContainer
+ public void testIsInsideScrollableRegion_offset() {
+ mStackScroller.setLeftTopRightBottom(1000, 0, 2000, 2000);
+ mStackScroller.setScrimClippingShape(createScrimShape(100, 500, 900, 2000));
+
+ MotionEvent event1 = transformEventForView(createMotionEvent(1500f, 400f), mStackScroller);
+ assertThat(mStackScroller.isInScrollableRegion(event1)).isFalse();
+
+ MotionEvent event2 = transformEventForView(createMotionEvent(1050, 1000f), mStackScroller);
+ assertThat(mStackScroller.isInScrollableRegion(event2)).isFalse();
+
+ MotionEvent event3 = transformEventForView(createMotionEvent(1950f, 1000f), mStackScroller);
+ assertThat(mStackScroller.isInScrollableRegion(event3)).isFalse();
+
+ MotionEvent event4 = transformEventForView(createMotionEvent(1500f, 1000f), mStackScroller);
+ assertThat(mStackScroller.isInScrollableRegion(event4)).isTrue();
+ }
+
+ @Test
@DisableSceneContainer // TODO(b/312473478): address disabled test
public void setFractionToShade_recomputesStackHeight() {
mStackScroller.setFractionToShade(1f);
@@ -1438,7 +1487,7 @@
private static MotionEvent transformEventForView(MotionEvent event, View view) {
// From `ViewGroup#dispatchTransformedTouchEvent`
MotionEvent transformed = event.copy();
- transformed.offsetLocation(-view.getTop(), -view.getLeft());
+ transformed.offsetLocation(/* deltaX = */-view.getLeft(), /* deltaY = */ -view.getTop());
return transformed;
}
@@ -1474,4 +1523,9 @@
}
private abstract static class BooleanConsumer implements Consumer<Boolean> { }
+
+ private ShadeScrimShape createScrimShape(int left, int top, int right, int bottom) {
+ ShadeScrimBounds bounds = new ShadeScrimBounds(left, top, right, bottom);
+ return new ShadeScrimShape(bounds, 0, 0);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 3e3c046..1d74331 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -779,6 +779,26 @@
@Test
@DisableSceneContainer
+ public void testResetDoesNotHideBouncerWhenNotShowing() {
+ reset(mDismissCallbackRegistry);
+ reset(mPrimaryBouncerInteractor);
+
+ // GIVEN the keyguard is showing
+ reset(mAlternateBouncerInteractor);
+ when(mKeyguardStateController.isShowing()).thenReturn(true);
+ when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(false);
+
+ // WHEN SBKV is reset with hideBouncerWhenShowing=true
+ mStatusBarKeyguardViewManager.reset(true);
+
+ // THEN no calls to hide should be made
+ verify(mAlternateBouncerInteractor, never()).hide();
+ verify(mDismissCallbackRegistry, never()).notifyDismissCancelled();
+ verify(mPrimaryBouncerInteractor, never()).setDismissAction(eq(null), eq(null));
+ }
+
+ @Test
+ @DisableSceneContainer
public void testResetHideBouncerWhenShowing_alternateBouncerHides() {
reset(mDismissCallbackRegistry);
reset(mPrimaryBouncerInteractor);
@@ -786,6 +806,7 @@
// GIVEN the keyguard is showing
reset(mAlternateBouncerInteractor);
when(mKeyguardStateController.isShowing()).thenReturn(true);
+ when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(true);
// WHEN SBKV is reset with hideBouncerWhenShowing=true
mStatusBarKeyguardViewManager.reset(true);
@@ -1091,9 +1112,11 @@
public void testShowBouncerOrKeyguard_showsKeyguardIfShowBouncerReturnsFalse() {
when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(
KeyguardSecurityModel.SecurityMode.SimPin);
+ // Returning false means unable to show the bouncer
when(mPrimaryBouncerInteractor.show(true)).thenReturn(false);
when(mKeyguardTransitionInteractor.getTransitionState().getValue().getTo())
.thenReturn(KeyguardState.LOCKSCREEN);
+ mStatusBarKeyguardViewManager.onStartedWakingUp();
reset(mCentralSurfaces);
// Advance past reattempts
@@ -1106,6 +1129,23 @@
@Test
@DisableSceneContainer
+ @EnableFlags(Flags.FLAG_SIM_PIN_RACE_CONDITION_ON_RESTART)
+ public void testShowBouncerOrKeyguard_showsKeyguardIfSleeping() {
+ when(mKeyguardTransitionInteractor.getTransitionState().getValue().getTo())
+ .thenReturn(KeyguardState.LOCKSCREEN);
+ mStatusBarKeyguardViewManager.onStartedGoingToSleep();
+
+ reset(mCentralSurfaces);
+ reset(mPrimaryBouncerInteractor);
+ mStatusBarKeyguardViewManager.showBouncerOrKeyguard(
+ /* hideBouncerWhenShowing= */true, false);
+ verify(mCentralSurfaces).showKeyguard();
+ verify(mPrimaryBouncerInteractor).hide();
+ }
+
+
+ @Test
+ @DisableSceneContainer
public void testShowBouncerOrKeyguard_needsFullScreen_bouncerAlreadyShowing() {
boolean isFalsingReset = false;
when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
index bea027f..6e337ef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
@@ -432,8 +432,7 @@
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -445,8 +444,7 @@
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.VISIBLE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.VISIBLE, getPrimaryOngoingActivityChipView().getVisibility());
assertEquals(View.INVISIBLE, getNotificationAreaView().getVisibility());
}
@@ -460,8 +458,7 @@
fragment.disable(DEFAULT_DISPLAY,
StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false);
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -474,8 +471,7 @@
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -487,22 +483,19 @@
when(mOngoingCallController.hasOngoingCall()).thenReturn(true);
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.VISIBLE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.VISIBLE, getPrimaryOngoingActivityChipView().getVisibility());
// Ongoing call ended
when(mOngoingCallController.hasOngoingCall()).thenReturn(false);
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
// Ongoing call started
when(mOngoingCallController.hasOngoingCall()).thenReturn(true);
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.VISIBLE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.VISIBLE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -536,8 +529,7 @@
/* hasOngoingActivity= */ false, /* shouldAnimate= */ false);
// THEN the old callback value is used, so the view is shown
- assertEquals(View.VISIBLE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.VISIBLE, getPrimaryOngoingActivityChipView().getVisibility());
// WHEN there's *no* ongoing call via old callback
when(mOngoingCallController.hasOngoingCall()).thenReturn(false);
@@ -548,8 +540,7 @@
/* hasOngoingActivity= */ true, /* shouldAnimate= */ false);
// THEN the old callback value is used, so the view is hidden
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -564,8 +555,7 @@
mCollapsedStatusBarViewBinder.getListener().onOngoingActivityStatusChanged(
/* hasOngoingActivity= */ false, /* shouldAnimate= */ false);
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -576,8 +566,7 @@
mCollapsedStatusBarViewBinder.getListener().onOngoingActivityStatusChanged(
/* hasOngoingActivity= */ true, /* shouldAnimate= */ false);
- assertEquals(View.VISIBLE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.VISIBLE, getPrimaryOngoingActivityChipView().getVisibility());
assertEquals(View.INVISIBLE, getNotificationAreaView().getVisibility());
}
@@ -592,8 +581,7 @@
fragment.disable(DEFAULT_DISPLAY,
StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false);
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -607,8 +595,7 @@
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -620,15 +607,13 @@
mCollapsedStatusBarViewBinder.getListener().onOngoingActivityStatusChanged(
/* hasOngoingActivity= */ true, /* shouldAnimate= */ false);
- assertEquals(View.VISIBLE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.VISIBLE, getPrimaryOngoingActivityChipView().getVisibility());
// Ongoing activity ended
mCollapsedStatusBarViewBinder.getListener().onOngoingActivityStatusChanged(
/* hasOngoingActivity= */ false, /* shouldAnimate= */ false);
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -661,8 +646,7 @@
/* hasOngoingActivity= */ false, /* shouldAnimate= */ false);
// THEN the new callback value is used, so the view is hidden
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
// WHEN there's *no* ongoing call via old callback
when(mOngoingCallController.hasOngoingCall()).thenReturn(false);
@@ -673,8 +657,7 @@
/* hasOngoingActivity= */ true, /* shouldAnimate= */ false);
// THEN the new callback value is used, so the view is shown
- assertEquals(View.VISIBLE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.VISIBLE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -1023,4 +1006,8 @@
private View getNotificationAreaView() {
return mFragment.getView().findViewById(R.id.notificationIcons);
}
+
+ private View getPrimaryOngoingActivityChipView() {
+ return mFragment.getView().findViewById(R.id.ongoing_activity_chip_primary);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorTest.kt
index db3e533..7901f47 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorTest.kt
@@ -19,13 +19,11 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
-import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
-import com.android.systemui.util.mockito.mock
+import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.launchIn
@@ -39,9 +37,9 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class AirplaneModeInteractorTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
- private val mobileConnectionsRepository =
- FakeMobileConnectionsRepository(FakeMobileMappingsProxy(), mock<TableLogBuffer> {})
+ private val mobileConnectionsRepository = kosmos.fakeMobileConnectionsRepository
private val airplaneModeRepository = FakeAirplaneModeRepository()
private val connectivityRepository = FakeConnectivityRepository()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt
index b823333..8beed01 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt
@@ -19,12 +19,13 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
+import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -35,7 +36,6 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.Mock
import org.mockito.MockitoAnnotations
@SmallTest
@@ -43,10 +43,11 @@
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
@RunWith(AndroidJUnit4::class)
class AirplaneModeViewModelImplTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
private lateinit var underTest: AirplaneModeViewModelImpl
- @Mock private lateinit var logger: TableLogBuffer
+ private val logger = logcatTableLogBuffer(kosmos, "AirplaneModeViewModelImplTest")
private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
private lateinit var connectivityRepository: FakeConnectivityRepository
private lateinit var interactor: AirplaneModeInteractor
@@ -61,7 +62,7 @@
AirplaneModeInteractor(
airplaneModeRepository,
connectivityRepository,
- FakeMobileConnectionsRepository(),
+ kosmos.fakeMobileConnectionsRepository,
)
scope = CoroutineScope(IMMEDIATE)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
index 7d586cd..36f5236 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
@@ -27,7 +27,7 @@
import com.android.systemui.demomode.DemoModeController
import com.android.systemui.dump.DumpManager
import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.log.table.TableLogBufferFactory
+import com.android.systemui.log.table.tableLogBufferFactory
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
@@ -42,11 +42,11 @@
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.data.repository.demo.DemoModeWifiDataSource
+import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.kotlinArgumentCaptor
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -56,7 +56,6 @@
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
import org.junit.After
import org.junit.Before
import org.junit.Test
@@ -75,12 +74,13 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class MobileRepositorySwitcherTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+
private lateinit var underTest: MobileRepositorySwitcher
private lateinit var realRepo: MobileConnectionsRepositoryImpl
private lateinit var demoRepo: DemoMobileConnectionsRepository
private lateinit var mobileDataSource: DemoModeMobileConnectionDataSource
private lateinit var wifiDataSource: DemoModeWifiDataSource
- private lateinit var logFactory: TableLogBufferFactory
private lateinit var wifiRepository: FakeWifiRepository
private lateinit var connectivityRepository: ConnectivityRepository
@@ -95,16 +95,12 @@
private val mobileMappings = FakeMobileMappingsProxy()
private val subscriptionManagerProxy = FakeSubscriptionManagerProxy()
- private val testDispatcher = UnconfinedTestDispatcher()
private val scope = CoroutineScope(IMMEDIATE)
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- logFactory =
- TableLogBufferFactory(dumpManager, FakeSystemClock(), mock(), testDispatcher, scope)
-
// Never start in demo mode
whenever(demoModeController.isInDemoMode).thenReturn(false)
@@ -147,7 +143,7 @@
wifiDataSource = wifiDataSource,
scope = scope,
context = context,
- logFactory = logFactory,
+ logFactory = kosmos.tableLogBufferFactory,
)
underTest =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
index db6f5927..7d32021 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
@@ -23,16 +23,16 @@
import com.android.settingslib.SignalIcon
import com.android.settingslib.mobile.TelephonyIcons
import com.android.systemui.SysuiTestCase
-import com.android.systemui.log.table.TableLogBufferFactory
+import com.android.systemui.log.table.tableLogBufferFactory
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
+import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
@@ -43,12 +43,11 @@
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.After
-import platform.test.runner.parameterized.ParameterizedAndroidJunit4
-import platform.test.runner.parameterized.Parameters
-import platform.test.runner.parameterized.Parameter
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
/**
* Parameterized test for all of the common values of [FakeNetworkEventModel]. This test simply
@@ -60,19 +59,11 @@
@RunWith(ParameterizedAndroidJunit4::class)
internal class DemoMobileConnectionParameterizedTest(private val testCase: TestCase) :
SysuiTestCase() {
+ private val kosmos = testKosmos()
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
- private val logFactory =
- TableLogBufferFactory(
- mock(),
- FakeSystemClock(),
- mock(),
- testDispatcher,
- testScope.backgroundScope,
- )
-
private val fakeNetworkEventFlow = MutableStateFlow<FakeNetworkEventModel?>(null)
private val fakeWifiEventFlow = MutableStateFlow<FakeWifiEventModel?>(null)
@@ -99,7 +90,7 @@
wifiDataSource = mockWifiDataSource,
scope = testScope.backgroundScope,
context = context,
- logFactory = logFactory,
+ logFactory = kosmos.tableLogBufferFactory,
)
connectionsRepo.startProcessingCommands()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
index 5e0d2fb0..5017dda 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
@@ -24,8 +24,7 @@
import com.android.settingslib.SignalIcon
import com.android.settingslib.mobile.TelephonyIcons.THREE_G
import com.android.systemui.SysuiTestCase
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.log.table.TableLogBufferFactory
+import com.android.systemui.log.table.tableLogBufferFactory
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
@@ -34,9 +33,9 @@
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.model.FakeWifiEventModel
+import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import junit.framework.Assert
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -56,21 +55,13 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
- private val dumpManager: DumpManager = mock()
+ private val kosmos = testKosmos()
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
private val fakeNetworkEventFlow = MutableStateFlow<FakeNetworkEventModel?>(null)
private val fakeWifiEventFlow = MutableStateFlow<FakeWifiEventModel?>(null)
- private val logFactory =
- TableLogBufferFactory(
- dumpManager,
- FakeSystemClock(),
- mock(),
- testDispatcher,
- testScope.backgroundScope,
- )
private lateinit var underTest: DemoMobileConnectionsRepository
private lateinit var mobileDataSource: DemoModeMobileConnectionDataSource
@@ -94,7 +85,7 @@
wifiDataSource = wifiDataSource,
scope = testScope.backgroundScope,
context = context,
- logFactory = logFactory,
+ logFactory = kosmos.tableLogBufferFactory,
)
underTest.startProcessingCommands()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
index 237aabc..b6e23c1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepositoryTest.kt
@@ -104,7 +104,7 @@
underTest.dataConnectionState.onEach { latestConnState = it }.launchIn(this)
val netJob = underTest.resolvedNetworkType.onEach { latestNetType = it }.launchIn(this)
- wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = NET_ID, level = 1))
+ wifiRepository.setWifiNetwork(WifiNetworkModel.Active(level = 1))
assertThat(latestConnState).isEqualTo(DataConnectionState.Disconnected)
assertThat(latestNetType).isNotEqualTo(ResolvedNetworkType.CarrierMergedNetworkType)
@@ -124,7 +124,6 @@
wifiRepository.setWifiNetwork(
WifiNetworkModel.CarrierMerged(
- networkId = NET_ID,
subscriptionId = SUB_ID,
level = 3,
)
@@ -145,7 +144,6 @@
wifiRepository.setIsWifiDefault(true)
wifiRepository.setWifiNetwork(
WifiNetworkModel.CarrierMerged(
- networkId = NET_ID,
subscriptionId = SUB_ID,
level = 3,
)
@@ -183,7 +181,6 @@
wifiRepository.setWifiNetwork(
WifiNetworkModel.CarrierMerged(
- networkId = NET_ID,
subscriptionId = SUB_ID + 10,
level = 3,
)
@@ -205,7 +202,6 @@
wifiRepository.setWifiNetwork(
WifiNetworkModel.CarrierMerged(
- networkId = NET_ID,
subscriptionId = SUB_ID,
level = 3,
)
@@ -226,7 +222,6 @@
wifiRepository.setWifiNetwork(
WifiNetworkModel.CarrierMerged(
- networkId = NET_ID,
subscriptionId = SUB_ID,
level = 3,
)
@@ -246,7 +241,6 @@
wifiRepository.setWifiNetwork(
WifiNetworkModel.CarrierMerged(
- networkId = NET_ID,
subscriptionId = SUB_ID,
level = 1,
numberOfLevels = 6,
@@ -310,7 +304,6 @@
whenever(telephonyManager.simOperatorName).thenReturn("New SIM name")
wifiRepository.setWifiNetwork(
WifiNetworkModel.CarrierMerged(
- networkId = NET_ID,
subscriptionId = SUB_ID,
level = 3,
)
@@ -331,6 +324,5 @@
private companion object {
const val SUB_ID = 123
- const val NET_ID = 456
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
index fd4c370..a03980a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
@@ -29,8 +29,8 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.flags.Flags.ROAMING_INDICATOR_VIA_DISPLAY_INFO
-import com.android.systemui.log.table.TableLogBuffer
-import com.android.systemui.log.table.TableLogBufferFactory
+import com.android.systemui.log.table.logcatTableLogBuffer
+import com.android.systemui.log.table.tableLogBufferFactory
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
@@ -42,11 +42,11 @@
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.getTelephonyCallbackForType
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
+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.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import java.io.PrintWriter
import java.io.StringWriter
@@ -73,23 +73,16 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class FullMobileConnectionRepositoryTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+
private lateinit var underTest: FullMobileConnectionRepository
private val flags =
FakeFeatureFlagsClassic().also { it.set(ROAMING_INDICATOR_VIA_DISPLAY_INFO, true) }
- private val systemClock = FakeSystemClock()
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
- private val tableLogBuffer =
- TableLogBuffer(
- maxSize = 100,
- name = "TestName",
- systemClock,
- mock(),
- testDispatcher,
- testScope.backgroundScope,
- )
+ private val tableLogBuffer = logcatTableLogBuffer(kosmos, "TestName")
private val mobileFactory = mock<MobileConnectionRepositoryImpl.Factory>()
private val carrierMergedFactory = mock<CarrierMergedConnectionRepository.Factory>()
private val connectivityManager = mock<ConnectivityManager>()
@@ -372,19 +365,10 @@
@Test
fun factory_reusesLogBuffersForSameConnection() =
testScope.runTest {
- val realLoggerFactory =
- TableLogBufferFactory(
- mock(),
- FakeSystemClock(),
- mock(),
- testDispatcher,
- testScope.backgroundScope,
- )
-
val factory =
FullMobileConnectionRepository.Factory(
scope = testScope.backgroundScope,
- realLoggerFactory,
+ kosmos.tableLogBufferFactory,
mobileFactory,
carrierMergedFactory,
)
@@ -416,19 +400,10 @@
@Test
fun factory_reusesLogBuffersForSameSubIDevenIfCarrierMerged() =
testScope.runTest {
- val realLoggerFactory =
- TableLogBufferFactory(
- mock(),
- FakeSystemClock(),
- mock(),
- testDispatcher,
- testScope.backgroundScope,
- )
-
val factory =
FullMobileConnectionRepository.Factory(
scope = testScope.backgroundScope,
- realLoggerFactory,
+ kosmos.tableLogBufferFactory,
mobileFactory,
carrierMergedFactory,
)
@@ -512,10 +487,8 @@
val job = underTest.primaryLevel.launchIn(this)
// WHEN we set up carrier merged info
- val networkId = 2
wifiRepository.setWifiNetwork(
WifiNetworkModel.CarrierMerged(
- networkId,
SUB_ID,
level = 3,
)
@@ -527,7 +500,6 @@
// WHEN we update the info
wifiRepository.setWifiNetwork(
WifiNetworkModel.CarrierMerged(
- networkId,
SUB_ID,
level = 1,
)
@@ -565,10 +537,8 @@
assertThat(dumpBuffer()).contains("$COL_PRIMARY_LEVEL${BUFFER_SEPARATOR}1")
// WHEN isCarrierMerged is set to true
- val networkId = 2
wifiRepository.setWifiNetwork(
WifiNetworkModel.CarrierMerged(
- networkId,
SUB_ID,
level = 3,
)
@@ -581,7 +551,6 @@
// WHEN the carrier merge network is updated
wifiRepository.setWifiNetwork(
WifiNetworkModel.CarrierMerged(
- networkId,
SUB_ID,
level = 4,
)
@@ -632,10 +601,8 @@
.onSignalStrengthsChanged(signalStrength)
// THEN updates to the carrier merged level aren't logged
- val networkId = 2
wifiRepository.setWifiNetwork(
WifiNetworkModel.CarrierMerged(
- networkId,
SUB_ID,
level = 4,
)
@@ -644,7 +611,6 @@
wifiRepository.setWifiNetwork(
WifiNetworkModel.CarrierMerged(
- networkId,
SUB_ID,
level = 3,
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
index 171520f..7634490 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
@@ -88,7 +88,6 @@
import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.configWithOverride
import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.createTestConfig
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.signalStrength
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.telephonyDisplayInfo
@@ -121,7 +120,6 @@
@RunWith(AndroidJUnit4::class)
class MobileConnectionRepositoryTest : SysuiTestCase() {
private lateinit var underTest: MobileConnectionRepositoryImpl
- private lateinit var connectionsRepo: FakeMobileConnectionsRepository
private val flags =
FakeFeatureFlagsClassic().also { it.set(ROAMING_INDICATOR_VIA_DISPLAY_INFO, true) }
@@ -156,8 +154,6 @@
MockitoAnnotations.initMocks(this)
whenever(telephonyManager.subscriptionId).thenReturn(SUB_1_ID)
- connectionsRepo = FakeMobileConnectionsRepository(mobileMappings, tableLogger)
-
underTest =
MobileConnectionRepositoryImpl(
SUB_1_ID,
@@ -821,7 +817,7 @@
captor.lastValue.onReceive(context, intent)
// spnIntent() sets all values to true and test strings
- assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
+ assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
job.cancel()
}
@@ -856,7 +852,7 @@
verify(context).registerReceiver(captor.capture(), any())
captor.lastValue.onReceive(context, intent)
- assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
+ assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
// WHEN an intent with a different subId is sent
val wrongSubIntent = spnIntent(subId = 101)
@@ -864,7 +860,7 @@
captor.lastValue.onReceive(context, wrongSubIntent)
// THEN the previous intent's name is still used
- assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
+ assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
job.cancel()
}
@@ -906,7 +902,7 @@
verify(context).registerReceiver(captor.capture(), any())
captor.lastValue.onReceive(context, intent)
- assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
+ assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
val intentWithoutInfo =
spnIntent(
@@ -965,7 +961,7 @@
// The value is still there despite no active subscribers
assertThat(underTest.networkName.value)
- .isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
+ .isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
}
@Test
@@ -990,7 +986,7 @@
@Test
@EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
- fun networkName_allFieldsSet_doesNotUseDataSpn() =
+ fun networkName_allFieldsSet_prioritizesDataSpnOverSpn() =
testScope.runTest {
val latest by collectLastValue(underTest.networkName)
val captor = argumentCaptor<BroadcastReceiver>()
@@ -1006,6 +1002,27 @@
plmn = PLMN,
)
captor.lastValue.onReceive(context, intent)
+ assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
+ fun networkName_spnAndPlmn_fallbackToSpnWhenNullDataSpn() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.networkName)
+ val captor = argumentCaptor<BroadcastReceiver>()
+ verify(context).registerReceiver(captor.capture(), any())
+
+ val intent =
+ spnIntent(
+ subId = SUB_1_ID,
+ showSpn = true,
+ spn = SPN,
+ dataSpn = null,
+ showPlmn = true,
+ plmn = PLMN,
+ )
+ captor.lastValue.onReceive(context, intent)
assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
}
@@ -1047,7 +1064,27 @@
plmn = PLMN,
)
captor.lastValue.onReceive(context, intent)
- assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN"))
+ assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
+ fun networkName_showPlmn_plmnNotNull_showSpn_spnNotNull_dataSpnNull() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.networkName)
+ val captor = argumentCaptor<BroadcastReceiver>()
+ verify(context).registerReceiver(captor.capture(), any())
+ val intent =
+ spnIntent(
+ subId = SUB_1_ID,
+ showSpn = true,
+ spn = SPN,
+ dataSpn = null,
+ showPlmn = true,
+ plmn = PLMN,
+ )
+ captor.lastValue.onReceive(context, intent)
+ assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
}
@Test
@@ -1106,10 +1143,50 @@
plmn = null,
)
captor.lastValue.onReceive(context, intent)
+ assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$DATA_SPN"))
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
+ fun networkName_showPlmn_plmnNull_showSpn_dataSpnNull() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.networkName)
+ val captor = argumentCaptor<BroadcastReceiver>()
+ verify(context).registerReceiver(captor.capture(), any())
+ val intent =
+ spnIntent(
+ subId = SUB_1_ID,
+ showSpn = true,
+ spn = SPN,
+ dataSpn = null,
+ showPlmn = true,
+ plmn = null,
+ )
+ captor.lastValue.onReceive(context, intent)
assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$SPN"))
}
@Test
+ @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
+ fun networkName_showPlmn_plmnNull_showSpn_bothSpnNull() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.networkName)
+ val captor = argumentCaptor<BroadcastReceiver>()
+ verify(context).registerReceiver(captor.capture(), any())
+ val intent =
+ spnIntent(
+ subId = SUB_1_ID,
+ showSpn = true,
+ spn = null,
+ dataSpn = null,
+ showPlmn = true,
+ plmn = null,
+ )
+ captor.lastValue.onReceive(context, intent)
+ assertThat(latest).isEqualTo(DEFAULT_NAME_MODEL)
+ }
+
+ @Test
@DisableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
fun networkName_showPlmn_plmnNull_showSpn_flagOff() =
testScope.runTest {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt
index 2ab8c0a..0d82c79 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionTelephonySmokeTests.kt
@@ -42,7 +42,6 @@
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.getTelephonyCallbackForType
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileTelephonyHelpers.signalStrength
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
@@ -97,7 +96,6 @@
@SmallTest
class MobileConnectionTelephonySmokeTests : SysuiTestCase() {
private lateinit var underTest: MobileConnectionRepositoryImpl
- private lateinit var connectionsRepo: FakeMobileConnectionsRepository
private val flags =
FakeFeatureFlagsClassic().also { it.set(Flags.ROAMING_INDICATOR_VIA_DISPLAY_INFO, true) }
@@ -123,12 +121,6 @@
MockitoAnnotations.initMocks(this)
whenever(telephonyManager.subscriptionId).thenReturn(SUB_1_ID)
- connectionsRepo =
- FakeMobileConnectionsRepository(
- mobileMappings,
- tableLogger,
- )
-
underTest =
MobileConnectionRepositoryImpl(
SUB_1_ID,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
index 6de2caa..4b6e313 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
@@ -106,11 +106,7 @@
class MobileConnectionsRepositoryTest : SysuiTestCase() {
private val flags =
- FakeFeatureFlagsClassic().also {
- it.set(Flags.ROAMING_INDICATOR_VIA_DISPLAY_INFO, true)
- it.set(Flags.INSTANT_TETHER, true)
- it.set(Flags.WIFI_SECONDARY_NETWORKS, true)
- }
+ FakeFeatureFlagsClassic().also { it.set(Flags.ROAMING_INDICATOR_VIA_DISPLAY_INFO, true) }
private lateinit var connectionFactory: MobileConnectionRepositoryImpl.Factory
private lateinit var carrierMergedFactory: CarrierMergedConnectionRepository.Factory
@@ -189,7 +185,6 @@
wifiRepository =
WifiRepositoryImpl(
- flags,
testScope.backgroundScope,
mainExecutor,
testDispatcher,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
index e439aff..4fd830d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractorTest.kt
@@ -18,7 +18,6 @@
import android.platform.test.annotations.EnableFlags
import android.telephony.CellSignalStrength
-import android.telephony.SubscriptionManager.PROFILE_CLASS_UNSET
import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -27,12 +26,12 @@
import com.android.settingslib.mobile.TelephonyIcons
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.log.table.logcatTableLogBuffer
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.CarrierMergedNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType
-import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor.Companion.FIVE_G_OVERRIDE
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor.Companion.FOUR_G
@@ -40,12 +39,12 @@
import com.android.systemui.statusbar.pipeline.mobile.domain.model.NetworkTypeIconModel
import com.android.systemui.statusbar.pipeline.mobile.domain.model.SignalIconModel
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
+import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.test.TestScope
@@ -61,21 +60,18 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class MobileIconInteractorTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+
private lateinit var underTest: MobileIconInteractor
private val mobileMappingsProxy = FakeMobileMappingsProxy()
private val mobileIconsInteractor = FakeMobileIconsInteractor(mobileMappingsProxy, mock())
- private val subscriptionModel =
- MutableStateFlow(
- SubscriptionModel(
- subscriptionId = SUB_1_ID,
- carrierName = DEFAULT_NAME,
- profileClass = PROFILE_CLASS_UNSET,
- )
+ private val connectionRepository =
+ FakeMobileConnectionRepository(
+ SUB_1_ID,
+ logcatTableLogBuffer(kosmos, "MobileIconInteractorTest"),
)
- private val connectionRepository = FakeMobileConnectionRepository(SUB_1_ID, mock())
-
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
index e218fba..f6d439a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
@@ -28,7 +28,7 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.flags.Flags
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
@@ -36,10 +36,10 @@
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupRepository
+import com.android.systemui.testKosmos
import com.android.systemui.util.CarrierConfigTracker
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import java.util.UUID
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -58,6 +58,8 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class MobileIconsInteractorTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+
private lateinit var underTest: MobileIconsInteractor
private lateinit var connectivityRepository: FakeConnectivityRepository
private lateinit var connectionsRepository: FakeMobileConnectionsRepository
@@ -71,15 +73,7 @@
private val testDispatcher = StandardTestDispatcher()
private val testScope = TestScope(testDispatcher)
- private val tableLogBuffer =
- TableLogBuffer(
- 8,
- "MobileIconsInteractorTest",
- FakeSystemClock(),
- mock(),
- testDispatcher,
- testScope.backgroundScope,
- )
+ private val tableLogBuffer = logcatTableLogBuffer(kosmos, "MobileIconsInteractorTest")
@Mock private lateinit var carrierConfigTracker: CarrierConfigTracker
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt
index 42cb660..84846a1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/view/ModernStatusBarMobileViewTest.kt
@@ -28,12 +28,12 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.flags.Flags
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
import com.android.systemui.res.R
import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconInteractor
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
@@ -41,6 +41,7 @@
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.QsMobileIconViewModel
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
+import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -58,13 +59,13 @@
@RunWithLooper(setAsMainLooper = true)
@OptIn(ExperimentalCoroutinesApi::class)
class ModernStatusBarMobileViewTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
private lateinit var testableLooper: TestableLooper
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
private val flags = FakeFeatureFlagsClassic().also { it.set(Flags.NEW_NETWORK_SLICE_UI, false) }
- @Mock private lateinit var tableLogBuffer: TableLogBuffer
@Mock private lateinit var viewLogger: MobileViewLogger
@Mock private lateinit var constants: ConnectivityConstants
private lateinit var interactor: FakeMobileIconInteractor
@@ -88,10 +89,11 @@
AirplaneModeInteractor(
airplaneModeRepository,
FakeConnectivityRepository(),
- FakeMobileConnectionsRepository(),
+ kosmos.fakeMobileConnectionsRepository,
)
- interactor = FakeMobileIconInteractor(tableLogBuffer)
+ interactor =
+ FakeMobileIconInteractor(logcatTableLogBuffer(kosmos, "ModernStatusBarMobileViewTest"))
createViewModel()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
index deb9fcf..f99fcac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileIconViewModelTest.kt
@@ -21,24 +21,23 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.flags.Flags
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
import com.android.systemui.statusbar.connectivity.MobileIconCarrierIdOverridesFake
-import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconInteractor
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconInteractorImpl
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractorImpl
import com.android.systemui.statusbar.pipeline.mobile.domain.model.SignalIconModel
-import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupRepository
+import com.android.systemui.testKosmos
import com.android.systemui.util.CarrierConfigTracker
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
@@ -59,13 +58,15 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class LocationBasedMobileIconViewModelTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+
private lateinit var commonImpl: MobileIconViewModelCommon
private lateinit var homeIcon: HomeMobileIconViewModel
private lateinit var qsIcon: QsMobileIconViewModel
private lateinit var keyguardIcon: KeyguardMobileIconViewModel
private lateinit var iconsInteractor: MobileIconsInteractor
private lateinit var interactor: MobileIconInteractor
- private lateinit var connectionsRepository: FakeMobileConnectionsRepository
+ private val connectionsRepository = kosmos.fakeMobileConnectionsRepository
private lateinit var repository: FakeMobileConnectionRepository
private lateinit var airplaneModeInteractor: AirplaneModeInteractor
@@ -76,9 +77,9 @@
it.set(Flags.FILTER_PROVISIONING_NETWORK_SUBSCRIPTIONS, true)
}
- @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
@Mock private lateinit var constants: ConnectivityConstants
- @Mock private lateinit var tableLogBuffer: TableLogBuffer
+ private val tableLogBuffer =
+ logcatTableLogBuffer(kosmos, "LocationBasedMobileIconViewModelTest")
@Mock private lateinit var carrierConfigTracker: CarrierConfigTracker
private val testDispatcher = UnconfinedTestDispatcher()
@@ -91,10 +92,8 @@
AirplaneModeInteractor(
FakeAirplaneModeRepository(),
FakeConnectivityRepository(),
- FakeMobileConnectionsRepository(),
+ connectionsRepository,
)
- connectionsRepository =
- FakeMobileConnectionsRepository(FakeMobileMappingsProxy(), tableLogBuffer)
repository =
FakeMobileConnectionRepository(SUB_1_ID, tableLogBuffer).apply {
isInService.value = true
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
index e510924..4c7cdfa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
@@ -34,7 +34,7 @@
import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.flags.Flags
import com.android.systemui.flags.Flags.NEW_NETWORK_SLICE_UI
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
import com.android.systemui.res.R
import com.android.systemui.statusbar.connectivity.MobileIconCarrierIdOverridesFake
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
@@ -42,6 +42,7 @@
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconInteractorImpl
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractorImpl
import com.android.systemui.statusbar.pipeline.mobile.domain.model.SignalIconModel
@@ -51,6 +52,7 @@
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupRepository
+import com.android.systemui.testKosmos
import com.android.systemui.util.CarrierConfigTracker
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
@@ -74,6 +76,8 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class MobileIconViewModelTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+
private var connectivityRepository = FakeConnectivityRepository()
private lateinit var underTest: MobileIconViewModel
@@ -84,7 +88,7 @@
private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
private lateinit var airplaneModeInteractor: AirplaneModeInteractor
@Mock private lateinit var constants: ConnectivityConstants
- @Mock private lateinit var tableLogBuffer: TableLogBuffer
+ private val tableLogBuffer = logcatTableLogBuffer(kosmos, "MobileIconViewModelTest")
@Mock private lateinit var carrierConfigTracker: CarrierConfigTracker
private val flags =
@@ -118,7 +122,7 @@
AirplaneModeInteractor(
airplaneModeRepository,
connectivityRepository,
- FakeMobileConnectionsRepository(),
+ kosmos.fakeMobileConnectionsRepository,
)
iconsInteractor =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
index 47899a6..31ba837 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModelTest.kt
@@ -24,11 +24,10 @@
import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.flags.Flags
import com.android.systemui.statusbar.phone.StatusBarLocation
-import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor
import com.android.systemui.statusbar.pipeline.mobile.domain.model.NetworkTypeIconModel
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
@@ -36,6 +35,7 @@
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
+import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import junit.framework.Assert.assertFalse
@@ -58,12 +58,13 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class MobileIconsViewModelTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+
private lateinit var underTest: MobileIconsViewModel
private val interactor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock())
private val flags = FakeFeatureFlagsClassic().also { it.set(Flags.NEW_NETWORK_SLICE_UI, false) }
private lateinit var airplaneModeInteractor: AirplaneModeInteractor
- @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
@Mock private lateinit var constants: ConnectivityConstants
@Mock private lateinit var logger: MobileViewLogger
@Mock private lateinit var verboseLogger: VerboseMobileViewLogger
@@ -79,7 +80,7 @@
AirplaneModeInteractor(
FakeAirplaneModeRepository(),
FakeConnectivityRepository(),
- FakeMobileConnectionsRepository(),
+ kosmos.fakeMobileConnectionsRepository,
)
underTest =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt
index dbb77d5..a1cb29b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractorTest.kt
@@ -574,7 +574,7 @@
val latest by collectLastValue(underTest.isWifiActive)
// WHEN wifi is active
- wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = 0, level = 1))
+ wifiRepository.setWifiNetwork(WifiNetworkModel.Active(level = 1))
// THEN the interactor returns true due to the wifi network being active
assertThat(latest).isTrue()
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 bf31f1e..c1abf98 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
@@ -375,7 +375,7 @@
repo.isSatelliteProvisioned.value = true
// GIVEN wifi network is active
- wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = 0, level = 1))
+ wifiRepository.setWifiNetwork(WifiNetworkModel.Active(level = 1))
// THEN icon is null because the device is connected to wifi
assertThat(latest).isNull()
@@ -573,7 +573,7 @@
repo.isSatelliteProvisioned.value = true
// GIVEN wifi network is active
- wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = 0, level = 1))
+ wifiRepository.setWifiNetwork(WifiNetworkModel.Active(level = 1))
// THEN carrier text is null because the device is connected to wifi
assertThat(latest).isNull()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
index 60750cf..7ae6ea5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
@@ -415,9 +415,9 @@
}
@Test
- fun ongoingActivityChip_matchesViewModel() =
+ fun primaryOngoingActivityChip_matchesViewModel() =
testScope.runTest {
- val latest by collectLastValue(underTest.ongoingActivityChip)
+ val latest by collectLastValue(underTest.primaryOngoingActivityChip)
kosmos.screenRecordRepository.screenRecordState.value = ScreenRecordModel.Recording
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt
index cefdf7e..e71f521 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt
@@ -28,7 +28,7 @@
override val transitionFromLockscreenToDreamStartedEvent = MutableSharedFlow<Unit>()
- override val ongoingActivityChip: MutableStateFlow<OngoingActivityChipModel> =
+ override val primaryOngoingActivityChip: MutableStateFlow<OngoingActivityChipModel> =
MutableStateFlow(OngoingActivityChipModel.Hidden())
override val isHomeStatusBarAllowedByScene = MutableStateFlow(false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt
index 2238bff..fed3317 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt
@@ -26,7 +26,7 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.flags.Flags
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
import com.android.systemui.qs.tileimpl.QSTileImpl.ResourceIcon
import com.android.systemui.res.R
import com.android.systemui.statusbar.connectivity.WifiIcons
@@ -49,6 +49,7 @@
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiScanEntry
import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon
import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupRepository
+import com.android.systemui.testKosmos
import com.android.systemui.util.CarrierConfigTracker
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
@@ -61,6 +62,8 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class InternetTileViewModelTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+
private lateinit var underTest: InternetTileViewModel
private lateinit var mobileIconsInteractor: MobileIconsInteractor
@@ -73,7 +76,7 @@
private val wifiInteractor =
WifiInteractorImpl(connectivityRepository, wifiRepository, testScope.backgroundScope)
- private val tableLogBuffer: TableLogBuffer = mock()
+ private val tableLogBuffer = logcatTableLogBuffer(kosmos, "InternetTileViewModelTest")
private val carrierConfigTracker: CarrierConfigTracker = mock()
private val mobileConnectionsRepository =
@@ -152,7 +155,6 @@
val networkModel =
WifiNetworkModel.Active(
- networkId = 1,
level = 4,
ssid = "test ssid",
)
@@ -182,7 +184,6 @@
val networkModel =
WifiNetworkModel.Active(
- networkId = 1,
level = 4,
ssid = "test ssid",
hotspotDeviceType = WifiNetworkModel.HotspotDeviceType.NONE,
@@ -390,7 +391,6 @@
private fun setWifiNetworkWithHotspot(hotspot: WifiNetworkModel.HotspotDeviceType) {
val networkModel =
WifiNetworkModel.Active(
- networkId = 1,
level = 4,
ssid = "test ssid",
hotspotDeviceType = hotspot,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
index f8d50f5..46f34e8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
@@ -25,8 +25,6 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.connectivity.WifiPickerTrackerFactory
@@ -76,7 +74,6 @@
// inside each test case without needing to manually recreate the repository.
private val underTest: WifiRepositoryImpl by lazy {
WifiRepositoryImpl(
- featureFlags,
testScope.backgroundScope,
executor,
dispatcher,
@@ -89,7 +86,6 @@
private val executor = FakeExecutor(FakeSystemClock())
private val logger = LogBuffer("name", maxSize = 100, logcatEchoTracker = mock())
- private val featureFlags = FakeFeatureFlags()
private val tableLogger = mock<TableLogBuffer>()
private val wifiManager =
mock<WifiManager>().apply { whenever(this.maxSignalLevel).thenReturn(10) }
@@ -103,8 +99,6 @@
@Before
fun setUp() {
- featureFlags.set(Flags.INSTANT_TETHER, false)
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, false)
whenever(wifiPickerTrackerFactory.create(any(), capture(callbackCaptor), any()))
.thenReturn(wifiPickerTracker)
}
@@ -289,27 +283,6 @@
}
@Test
- fun accessPointInfo_alwaysFalse() =
- testScope.runTest {
- val latest by collectLastValue(underTest.wifiNetwork)
-
- val wifiEntry =
- mock<WifiEntry>().apply {
- whenever(this.isPrimaryNetwork).thenReturn(true)
- whenever(this.level).thenReturn(3)
- whenever(this.title).thenReturn(TITLE)
- }
- whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
- getCallback().onWifiEntriesChanged()
-
- assertThat(latest is WifiNetworkModel.Active).isTrue()
- val latestActive = latest as WifiNetworkModel.Active
- assertThat(latestActive.isPasspointAccessPoint).isFalse()
- assertThat(latestActive.isOnlineSignUpForPasspointAccessPoint).isFalse()
- assertThat(latestActive.passpointProviderFriendlyName).isNull()
- }
-
- @Test
fun wifiNetwork_unreachableLevel_inactiveNetwork() =
testScope.runTest {
val latest by collectLastValue(underTest.wifiNetwork)
@@ -394,7 +367,6 @@
@Test
fun wifiNetwork_notHotspot_none() =
testScope.runTest {
- featureFlags.set(Flags.INSTANT_TETHER, true)
val latest by collectLastValue(underTest.wifiNetwork)
val wifiEntry =
@@ -409,7 +381,6 @@
@Test
fun wifiNetwork_hotspot_unknown() =
testScope.runTest {
- featureFlags.set(Flags.INSTANT_TETHER, true)
val latest by collectLastValue(underTest.wifiNetwork)
val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_UNKNOWN)
@@ -423,7 +394,6 @@
@Test
fun wifiNetwork_hotspot_phone() =
testScope.runTest {
- featureFlags.set(Flags.INSTANT_TETHER, true)
val latest by collectLastValue(underTest.wifiNetwork)
val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
@@ -437,7 +407,6 @@
@Test
fun wifiNetwork_hotspot_tablet() =
testScope.runTest {
- featureFlags.set(Flags.INSTANT_TETHER, true)
val latest by collectLastValue(underTest.wifiNetwork)
val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_TABLET)
@@ -451,7 +420,6 @@
@Test
fun wifiNetwork_hotspot_laptop() =
testScope.runTest {
- featureFlags.set(Flags.INSTANT_TETHER, true)
val latest by collectLastValue(underTest.wifiNetwork)
val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_LAPTOP)
@@ -465,7 +433,6 @@
@Test
fun wifiNetwork_hotspot_watch() =
testScope.runTest {
- featureFlags.set(Flags.INSTANT_TETHER, true)
val latest by collectLastValue(underTest.wifiNetwork)
val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_WATCH)
@@ -479,7 +446,6 @@
@Test
fun wifiNetwork_hotspot_auto() =
testScope.runTest {
- featureFlags.set(Flags.INSTANT_TETHER, true)
val latest by collectLastValue(underTest.wifiNetwork)
val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_AUTO)
@@ -493,7 +459,6 @@
@Test
fun wifiNetwork_hotspot_invalid() =
testScope.runTest {
- featureFlags.set(Flags.INSTANT_TETHER, true)
val latest by collectLastValue(underTest.wifiNetwork)
val wifiEntry = createHotspotWithType(1234)
@@ -505,23 +470,6 @@
}
@Test
- fun wifiNetwork_hotspot_flagOff_valueNotUsed() =
- testScope.runTest {
- // WHEN the flag is off
- featureFlags.set(Flags.INSTANT_TETHER, false)
-
- val latest by collectLastValue(underTest.wifiNetwork)
-
- val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_WATCH)
- whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
- getCallback().onWifiEntriesChanged()
-
- // THEN NONE is always used, even if the wifi entry does have a hotspot device type
- assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
- .isEqualTo(WifiNetworkModel.HotspotDeviceType.NONE)
- }
-
- @Test
fun wifiNetwork_isCarrierMerged_flowHasCarrierMerged() =
testScope.runTest {
val latest by collectLastValue(underTest.wifiNetwork)
@@ -826,7 +774,6 @@
@Test
fun secondaryNetworks_activeEntriesEmpty_isEmpty() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf())
@@ -839,7 +786,6 @@
@Test
fun secondaryNetworks_oneActiveEntry_hasOne() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
val wifiEntry = mock<WifiEntry>()
@@ -853,7 +799,6 @@
@Test
fun secondaryNetworks_multipleActiveEntries_hasMultiple() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
val wifiEntry1 = mock<WifiEntry>()
@@ -868,7 +813,6 @@
@Test
fun secondaryNetworks_mapsToInactive() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
val inactiveEntry =
@@ -884,7 +828,6 @@
@Test
fun secondaryNetworks_mapsToActive() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
val activeEntry = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) }
@@ -900,7 +843,6 @@
@Test
fun secondaryNetworks_mapsToCarrierMerged() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
val carrierMergedEntry =
@@ -917,7 +859,6 @@
@Test
fun secondaryNetworks_mapsMultipleInOrder() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
val activeEntry = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) }
@@ -937,7 +878,6 @@
@Test
fun secondaryNetworks_filtersOutConnectedEntry() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
val connectedEntry = mock<WifiEntry>().apply { whenever(this.level).thenReturn(1) }
@@ -959,7 +899,6 @@
@Test
fun secondaryNetworks_noConnectedEntry_hasAllActiveEntries() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
val secondaryEntry1 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) }
@@ -978,7 +917,6 @@
@Test
fun secondaryNetworks_filtersOutPrimaryNetwork() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
val primaryEntry =
@@ -1001,20 +939,6 @@
}
@Test
- fun secondaryNetworks_flagOff_noNetworks() =
- testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, false)
- val latest by collectLastValue(underTest.secondaryNetworks)
-
- val wifiEntry = mock<WifiEntry>()
- whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(wifiEntry))
-
- getCallback().onWifiEntriesChanged()
-
- assertThat(latest).isEmpty()
- }
-
- @Test
fun isWifiConnectedWithValidSsid_inactiveNetwork_false() =
testScope.runTest {
collectLastValue(underTest.wifiNetwork)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt
index eb6b068..92860ef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModelTest.kt
@@ -34,31 +34,30 @@
@Test
fun active_levelsInValidRange_noException() {
(MIN_VALID_LEVEL..MAX_VALID_LEVEL).forEach { level ->
- WifiNetworkModel.Active(NETWORK_ID, level = level)
+ WifiNetworkModel.Active(level = level)
// No assert, just need no crash
}
}
@Test(expected = IllegalArgumentException::class)
fun active_levelNegative_exceptionThrown() {
- WifiNetworkModel.Active(NETWORK_ID, level = MIN_VALID_LEVEL - 1)
+ WifiNetworkModel.Active(level = MIN_VALID_LEVEL - 1)
}
@Test(expected = IllegalArgumentException::class)
fun active_levelTooHigh_exceptionThrown() {
- WifiNetworkModel.Active(NETWORK_ID, level = MAX_VALID_LEVEL + 1)
+ WifiNetworkModel.Active(level = MAX_VALID_LEVEL + 1)
}
@Test(expected = IllegalArgumentException::class)
fun carrierMerged_invalidSubId_exceptionThrown() {
- WifiNetworkModel.CarrierMerged(NETWORK_ID, INVALID_SUBSCRIPTION_ID, 1)
+ WifiNetworkModel.CarrierMerged(INVALID_SUBSCRIPTION_ID, 1)
}
@Test
fun active_hasValidSsid_nullSsid_false() {
val network =
WifiNetworkModel.Active(
- NETWORK_ID,
level = MAX_VALID_LEVEL,
ssid = null,
)
@@ -70,7 +69,6 @@
fun active_hasValidSsid_unknownSsid_false() {
val network =
WifiNetworkModel.Active(
- NETWORK_ID,
level = MAX_VALID_LEVEL,
ssid = UNKNOWN_SSID,
)
@@ -82,7 +80,6 @@
fun active_hasValidSsid_validSsid_true() {
val network =
WifiNetworkModel.Active(
- NETWORK_ID,
level = MAX_VALID_LEVEL,
ssid = "FakeSsid",
)
@@ -97,7 +94,6 @@
val logger = TestLogger()
val prevVal =
WifiNetworkModel.CarrierMerged(
- networkId = 5,
subscriptionId = 3,
level = 1,
)
@@ -105,7 +101,6 @@
WifiNetworkModel.Inactive.logDiffs(prevVal, logger)
assertThat(logger.changes).contains(Pair(COL_NETWORK_TYPE, TYPE_INACTIVE))
- assertThat(logger.changes).contains(Pair(COL_NETWORK_ID, NETWORK_ID_DEFAULT.toString()))
assertThat(logger.changes).contains(Pair(COL_VALIDATED, "false"))
assertThat(logger.changes).contains(Pair(COL_LEVEL, LEVEL_DEFAULT.toString()))
assertThat(logger.changes).contains(Pair(COL_SSID, "null"))
@@ -116,7 +111,6 @@
val logger = TestLogger()
val carrierMerged =
WifiNetworkModel.CarrierMerged(
- networkId = 6,
subscriptionId = 3,
level = 2,
)
@@ -124,7 +118,6 @@
carrierMerged.logDiffs(prevVal = WifiNetworkModel.Inactive, logger)
assertThat(logger.changes).contains(Pair(COL_NETWORK_TYPE, TYPE_CARRIER_MERGED))
- assertThat(logger.changes).contains(Pair(COL_NETWORK_ID, "6"))
assertThat(logger.changes).contains(Pair(COL_SUB_ID, "3"))
assertThat(logger.changes).contains(Pair(COL_VALIDATED, "true"))
assertThat(logger.changes).contains(Pair(COL_LEVEL, "2"))
@@ -136,7 +129,6 @@
val logger = TestLogger()
val activeNetwork =
WifiNetworkModel.Active(
- networkId = 5,
isValidated = true,
level = 3,
ssid = "Test SSID",
@@ -146,27 +138,21 @@
activeNetwork.logDiffs(prevVal = WifiNetworkModel.Inactive, logger)
assertThat(logger.changes).contains(Pair(COL_NETWORK_TYPE, TYPE_ACTIVE))
- assertThat(logger.changes).contains(Pair(COL_NETWORK_ID, "5"))
assertThat(logger.changes).contains(Pair(COL_VALIDATED, "true"))
assertThat(logger.changes).contains(Pair(COL_LEVEL, "3"))
assertThat(logger.changes).contains(Pair(COL_SSID, "Test SSID"))
assertThat(logger.changes).contains(Pair(COL_HOTSPOT, "LAPTOP"))
}
+
@Test
fun logDiffs_activeToInactive_resetsAllActiveFields() {
val logger = TestLogger()
val activeNetwork =
- WifiNetworkModel.Active(
- networkId = 5,
- isValidated = true,
- level = 3,
- ssid = "Test SSID"
- )
+ WifiNetworkModel.Active(isValidated = true, level = 3, ssid = "Test SSID")
WifiNetworkModel.Inactive.logDiffs(prevVal = activeNetwork, logger)
assertThat(logger.changes).contains(Pair(COL_NETWORK_TYPE, TYPE_INACTIVE))
- assertThat(logger.changes).contains(Pair(COL_NETWORK_ID, NETWORK_ID_DEFAULT.toString()))
assertThat(logger.changes).contains(Pair(COL_VALIDATED, "false"))
assertThat(logger.changes).contains(Pair(COL_LEVEL, LEVEL_DEFAULT.toString()))
assertThat(logger.changes).contains(Pair(COL_SSID, "null"))
@@ -178,7 +164,6 @@
val logger = TestLogger()
val activeNetwork =
WifiNetworkModel.Active(
- networkId = 5,
isValidated = true,
level = 3,
ssid = "Test SSID",
@@ -186,7 +171,6 @@
)
val prevVal =
WifiNetworkModel.CarrierMerged(
- networkId = 5,
subscriptionId = 3,
level = 1,
)
@@ -194,25 +178,19 @@
activeNetwork.logDiffs(prevVal, logger)
assertThat(logger.changes).contains(Pair(COL_NETWORK_TYPE, TYPE_ACTIVE))
- assertThat(logger.changes).contains(Pair(COL_NETWORK_ID, "5"))
assertThat(logger.changes).contains(Pair(COL_VALIDATED, "true"))
assertThat(logger.changes).contains(Pair(COL_LEVEL, "3"))
assertThat(logger.changes).contains(Pair(COL_SSID, "Test SSID"))
assertThat(logger.changes).contains(Pair(COL_HOTSPOT, "AUTO"))
}
+
@Test
fun logDiffs_activeToCarrierMerged_logsAllFields() {
val logger = TestLogger()
val activeNetwork =
- WifiNetworkModel.Active(
- networkId = 5,
- isValidated = true,
- level = 3,
- ssid = "Test SSID"
- )
+ WifiNetworkModel.Active(isValidated = true, level = 3, ssid = "Test SSID")
val carrierMerged =
WifiNetworkModel.CarrierMerged(
- networkId = 6,
subscriptionId = 3,
level = 2,
)
@@ -220,7 +198,6 @@
carrierMerged.logDiffs(prevVal = activeNetwork, logger)
assertThat(logger.changes).contains(Pair(COL_NETWORK_TYPE, TYPE_CARRIER_MERGED))
- assertThat(logger.changes).contains(Pair(COL_NETWORK_ID, "6"))
assertThat(logger.changes).contains(Pair(COL_SUB_ID, "3"))
assertThat(logger.changes).contains(Pair(COL_VALIDATED, "true"))
assertThat(logger.changes).contains(Pair(COL_LEVEL, "2"))
@@ -231,19 +208,9 @@
fun logDiffs_activeChangesLevel_onlyLevelLogged() {
val logger = TestLogger()
val prevActiveNetwork =
- WifiNetworkModel.Active(
- networkId = 5,
- isValidated = true,
- level = 3,
- ssid = "Test SSID"
- )
+ WifiNetworkModel.Active(isValidated = true, level = 3, ssid = "Test SSID")
val newActiveNetwork =
- WifiNetworkModel.Active(
- networkId = 5,
- isValidated = true,
- level = 2,
- ssid = "Test SSID"
- )
+ WifiNetworkModel.Active(isValidated = true, level = 2, ssid = "Test SSID")
newActiveNetwork.logDiffs(prevActiveNetwork, logger)
@@ -265,8 +232,4 @@
changes.add(Pair(columnName, value.toString()))
}
}
-
- companion object {
- private const val NETWORK_ID = 2
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
index 80b10c0..ff398f9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
@@ -26,7 +26,7 @@
import android.widget.ImageView
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.log.table.TableLogBuffer
+import com.android.systemui.log.table.logcatTableLogBuffer
import com.android.systemui.res.R
import com.android.systemui.statusbar.StatusBarIconView.STATE_DOT
import com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN
@@ -36,7 +36,7 @@
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
@@ -47,6 +47,7 @@
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel.Companion.viewModelForLocation
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel
+import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -61,10 +62,11 @@
@RunWith(AndroidTestingRunner::class)
@RunWithLooper(setAsMainLooper = true)
class ModernStatusBarWifiViewTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
private lateinit var testableLooper: TestableLooper
- @Mock private lateinit var tableLogBuffer: TableLogBuffer
+ private val tableLogBuffer = logcatTableLogBuffer(kosmos, "ModernStatusBarWifiViewTest")
@Mock private lateinit var connectivityConstants: ConnectivityConstants
@Mock private lateinit var wifiConstants: WifiConstants
private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
@@ -91,7 +93,7 @@
AirplaneModeInteractor(
airplaneModeRepository,
connectivityRepository,
- FakeMobileConnectionsRepository(),
+ kosmos.fakeMobileConnectionsRepository,
),
tableLogBuffer,
scope,
@@ -193,9 +195,7 @@
@Test
fun isIconVisible_notEnabled_outputsFalse() {
wifiRepository.setIsWifiEnabled(false)
- wifiRepository.setWifiNetwork(
- WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 2)
- )
+ wifiRepository.setWifiNetwork(WifiNetworkModel.Active(isValidated = true, level = 2))
val view = ModernStatusBarWifiView.constructAndBind(context, SLOT_NAME, viewModel)
@@ -210,9 +210,7 @@
@Test
fun isIconVisible_enabled_outputsTrue() {
wifiRepository.setIsWifiEnabled(true)
- wifiRepository.setWifiNetwork(
- WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 2)
- )
+ wifiRepository.setWifiNetwork(WifiNetworkModel.Active(isValidated = true, level = 2))
val view = ModernStatusBarWifiView.constructAndBind(context, SLOT_NAME, viewModel)
@@ -270,4 +268,3 @@
}
private const val SLOT_NAME = "TestSlotName"
-private const val NETWORK_ID = 200
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
index 489319e..82acb40 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt
@@ -31,7 +31,7 @@
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
@@ -42,6 +42,7 @@
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon
import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon.Companion.NO_INTERNET
+import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -64,6 +65,7 @@
@RunWith(Parameterized::class)
internal class WifiViewModelIconParameterizedTest(private val testCase: TestCase) :
SysuiTestCase() {
+ private val kosmos = testKosmos()
private lateinit var underTest: WifiViewModel
@@ -91,7 +93,7 @@
AirplaneModeInteractor(
airplaneModeRepository,
connectivityRepository,
- FakeMobileConnectionsRepository(),
+ kosmos.fakeMobileConnectionsRepository,
),
tableLogBuffer,
scope,
@@ -204,8 +206,7 @@
// Enabled = false => no networks shown
TestCase(
enabled = false,
- network =
- WifiNetworkModel.CarrierMerged(NETWORK_ID, subscriptionId = 1, level = 1),
+ network = WifiNetworkModel.CarrierMerged(subscriptionId = 1, level = 1),
expected = null,
),
TestCase(
@@ -215,20 +216,19 @@
),
TestCase(
enabled = false,
- network = WifiNetworkModel.Active(NETWORK_ID, isValidated = false, level = 1),
+ network = WifiNetworkModel.Active(isValidated = false, level = 1),
expected = null,
),
TestCase(
enabled = false,
- network = WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 3),
+ network = WifiNetworkModel.Active(isValidated = true, level = 3),
expected = null,
),
// forceHidden = true => no networks shown
TestCase(
forceHidden = true,
- network =
- WifiNetworkModel.CarrierMerged(NETWORK_ID, subscriptionId = 1, level = 1),
+ network = WifiNetworkModel.CarrierMerged(subscriptionId = 1, level = 1),
expected = null,
),
TestCase(
@@ -238,12 +238,12 @@
),
TestCase(
enabled = false,
- network = WifiNetworkModel.Active(NETWORK_ID, isValidated = false, level = 2),
+ network = WifiNetworkModel.Active(isValidated = false, level = 2),
expected = null,
),
TestCase(
forceHidden = true,
- network = WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 1),
+ network = WifiNetworkModel.Active(isValidated = true, level = 1),
expected = null,
),
@@ -263,7 +263,7 @@
),
TestCase(
alwaysShowIconWhenEnabled = true,
- network = WifiNetworkModel.Active(NETWORK_ID, isValidated = false, level = 4),
+ network = WifiNetworkModel.Active(isValidated = false, level = 4),
expected =
Expected(
iconResource = WIFI_NO_INTERNET_ICONS[4],
@@ -276,7 +276,7 @@
),
TestCase(
alwaysShowIconWhenEnabled = true,
- network = WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 2),
+ network = WifiNetworkModel.Active(isValidated = true, level = 2),
expected =
Expected(
iconResource = WIFI_FULL_ICONS[2],
@@ -303,7 +303,7 @@
),
TestCase(
hasDataCapabilities = false,
- network = WifiNetworkModel.Active(NETWORK_ID, isValidated = false, level = 2),
+ network = WifiNetworkModel.Active(isValidated = false, level = 2),
expected =
Expected(
iconResource = WIFI_NO_INTERNET_ICONS[2],
@@ -316,7 +316,7 @@
),
TestCase(
hasDataCapabilities = false,
- network = WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 0),
+ network = WifiNetworkModel.Active(isValidated = true, level = 0),
expected =
Expected(
iconResource = WIFI_FULL_ICONS[0],
@@ -343,7 +343,7 @@
),
TestCase(
isDefault = true,
- network = WifiNetworkModel.Active(NETWORK_ID, isValidated = false, level = 3),
+ network = WifiNetworkModel.Active(isValidated = false, level = 3),
expected =
Expected(
iconResource = WIFI_NO_INTERNET_ICONS[3],
@@ -356,7 +356,7 @@
),
TestCase(
isDefault = true,
- network = WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 1),
+ network = WifiNetworkModel.Active(isValidated = true, level = 1),
expected =
Expected(
iconResource = WIFI_FULL_ICONS[1],
@@ -372,8 +372,7 @@
enabled = true,
isDefault = true,
forceHidden = false,
- network =
- WifiNetworkModel.CarrierMerged(NETWORK_ID, subscriptionId = 1, level = 1),
+ network = WifiNetworkModel.CarrierMerged(subscriptionId = 1, level = 1),
expected = null,
),
@@ -390,7 +389,7 @@
),
TestCase(
isDefault = false,
- network = WifiNetworkModel.Active(NETWORK_ID, isValidated = false, level = 3),
+ network = WifiNetworkModel.Active(isValidated = false, level = 3),
expected = null,
),
@@ -398,7 +397,7 @@
// because wifi isn't the default connection (b/272509965).
TestCase(
isDefault = false,
- network = WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 4),
+ network = WifiNetworkModel.Active(isValidated = true, level = 4),
expected = null,
),
)
@@ -406,4 +405,3 @@
}
private val IMMEDIATE = Dispatchers.Main.immediate
-private const val NETWORK_ID = 789
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java
index 0358474..3041240 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.UserHandle;
@@ -40,6 +41,7 @@
@GuardedBy("mRegisteredReceivers")
private final Set<BroadcastReceiver> mRegisteredReceivers = new ArraySet<>();
private final Map<UserHandle, Context> mContextForUser = new HashMap<>();
+ private final Map<String, Context> mContextForPackage = new HashMap<>();
public SysuiTestableContext(Context base) {
super(base);
@@ -175,4 +177,22 @@
}
return super.createContextAsUser(user, flags);
}
+
+ /**
+ * Sets a Context object that will be returned as the result of {@link #createPackageContext}
+ * for a specific {@code packageName}.
+ */
+ public void prepareCreatePackageContext(String packageName, Context context) {
+ mContextForPackage.put(packageName, context);
+ }
+
+ @Override
+ public Context createPackageContext(String packageName, int flags)
+ throws PackageManager.NameNotFoundException {
+ Context packageContext = mContextForPackage.get(packageName);
+ if (packageContext != null) {
+ return packageContext;
+ }
+ return super.createPackageContext(packageName, flags);
+ }
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceLoggerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/CaptioningRepositoryKosmos.kt
similarity index 74%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceLoggerKosmos.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/CaptioningRepositoryKosmos.kt
index 76d71dd..5c39e32 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceLoggerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/CaptioningRepositoryKosmos.kt
@@ -14,10 +14,9 @@
* limitations under the License.
*/
-package com.android.systemui.media.controls.domain.pipeline
+package com.android.systemui.accessibility.data.repository
import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.log.logcatLogBuffer
-var Kosmos.mediaDeviceLogger by
- Kosmos.Fixture { MediaDeviceLogger(logcatLogBuffer("MediaDeviceLoggerKosmos")) }
+var Kosmos.fakeCaptioningRepository by Kosmos.Fixture { FakeCaptioningRepository() }
+val Kosmos.captioningRepository by Kosmos.Fixture { fakeCaptioningRepository }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/FakeCaptioningRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/FakeCaptioningRepository.kt
new file mode 100644
index 0000000..a639463
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/data/repository/FakeCaptioningRepository.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.accessibility.data.repository
+
+import com.android.systemui.accessibility.data.model.CaptioningModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+class FakeCaptioningRepository : CaptioningRepository {
+
+ private val mutableCaptioningModel = MutableStateFlow<CaptioningModel?>(null)
+ override val captioningModel: StateFlow<CaptioningModel?> = mutableCaptioningModel.asStateFlow()
+
+ override suspend fun setIsSystemAudioCaptioningEnabled(isEnabled: Boolean) {
+ mutableCaptioningModel.value =
+ CaptioningModel(
+ isSystemAudioCaptioningEnabled = isEnabled,
+ isSystemAudioCaptioningUiEnabled =
+ mutableCaptioningModel.value?.isSystemAudioCaptioningUiEnabled == true,
+ )
+ }
+
+ fun setIsSystemAudioCaptioningUiEnabled(isEnabled: Boolean) {
+ mutableCaptioningModel.value =
+ CaptioningModel(
+ isSystemAudioCaptioningEnabled =
+ mutableCaptioningModel.value?.isSystemAudioCaptioningEnabled == true,
+ isSystemAudioCaptioningUiEnabled = isEnabled,
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/view/accessibility/data/repository/CaptioningKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/domain/interactor/CaptioningInteractorKosmos.kt
similarity index 76%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/view/accessibility/data/repository/CaptioningKosmos.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/domain/interactor/CaptioningInteractorKosmos.kt
index 0e978f2..2125e95 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/view/accessibility/data/repository/CaptioningKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/accessibility/domain/interactor/CaptioningInteractorKosmos.kt
@@ -14,10 +14,9 @@
* limitations under the License.
*/
-package com.android.systemui.view.accessibility.data.repository
+package com.android.systemui.accessibility.domain.interactor
-import com.android.settingslib.view.accessibility.domain.interactor.CaptioningInteractor
+import com.android.systemui.accessibility.data.repository.captioningRepository
import com.android.systemui.kosmos.Kosmos
-val Kosmos.captioningRepository by Kosmos.Fixture { FakeCaptioningRepository() }
val Kosmos.captioningInteractor by Kosmos.Fixture { CaptioningInteractor(captioningRepository) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorKosmos.kt
index 5ced578..3087d01 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorKosmos.kt
@@ -26,6 +26,7 @@
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.statusbar.pipeline.mobile.data.repository.mobileConnectionsRepository
import com.android.systemui.telephony.domain.interactor.telephonyInteractor
import com.android.systemui.user.domain.interactor.selectedUserInteractor
@@ -50,5 +51,6 @@
},
metricsLogger = metricsLogger,
dozeLogger = mock(),
+ sceneInteractor = { sceneInteractor },
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt
index 171be97..649e4e8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt
@@ -33,16 +33,16 @@
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.StateFlow
-val Kosmos.bouncerSceneActionsViewModel by Fixture {
- BouncerSceneActionsViewModel(
+val Kosmos.bouncerUserActionsViewModel by Fixture {
+ BouncerUserActionsViewModel(
bouncerInteractor = bouncerInteractor,
)
}
-val Kosmos.bouncerSceneActionsViewModelFactory by Fixture {
- object : BouncerSceneActionsViewModel.Factory {
- override fun create(): BouncerSceneActionsViewModel {
- return bouncerSceneActionsViewModel
+val Kosmos.bouncerUserActionsViewModelFactory by Fixture {
+ object : BouncerUserActionsViewModel.Factory {
+ override fun create(): BouncerUserActionsViewModel {
+ return bouncerUserActionsViewModel
}
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/VibratorHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/VibratorHelperKosmos.kt
index 434953f..ff71f2f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/VibratorHelperKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/VibratorHelperKosmos.kt
@@ -17,5 +17,7 @@
package com.android.systemui.haptics
import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.statusbar.VibratorHelper
-var Kosmos.vibratorHelper by Kosmos.Fixture { FakeVibratorHelper() }
+var Kosmos.vibratorHelper: VibratorHelper by Kosmos.Fixture { fakeVibratorHelper }
+val Kosmos.fakeVibratorHelper by Kosmos.Fixture { FakeVibratorHelper() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/MSDLPlayerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/MSDLPlayerKosmos.kt
index f5a05b4..4f5c32a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/MSDLPlayerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/MSDLPlayerKosmos.kt
@@ -17,5 +17,7 @@
package com.android.systemui.haptics.msdl
import com.android.systemui.kosmos.Kosmos
+import com.google.android.msdl.domain.MSDLPlayer
-val Kosmos.msdlPlayer by Kosmos.Fixture { FakeMSDLPlayer() }
+var Kosmos.msdlPlayer: MSDLPlayer by Kosmos.Fixture { fakeMSDLPlayer }
+val Kosmos.fakeMSDLPlayer by Kosmos.Fixture { FakeMSDLPlayer() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt
index 1e95fc1..740d891 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt
@@ -34,6 +34,7 @@
import com.android.systemui.keyguard.ui.viewmodel.alternateBouncerWindowViewModel
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.statusbar.gesture.TapGestureDetector
import com.android.systemui.util.mockito.mock
@@ -64,6 +65,7 @@
},
messageAreaViewModel = mock<AlternateBouncerMessageAreaViewModel>(),
powerInteractor = powerInteractor,
+ touchLogBuffer = logcatLogBuffer(),
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelKosmos.kt
similarity index 63%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelKosmos.kt
index 2387aa8..a25b29fd 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelKosmos.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.
@@ -14,16 +14,18 @@
* limitations under the License.
*/
-package com.android.systemui.shade.ui.viewmodel
+package com.android.systemui.keyguard.ui.viewmodel
+import com.android.systemui.communal.domain.interactor.communalInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
-import com.android.systemui.qs.ui.adapter.qsSceneAdapter
import com.android.systemui.shade.domain.interactor.shadeInteractor
-val Kosmos.shadeSceneActionsViewModel: ShadeSceneActionsViewModel by Fixture {
- ShadeSceneActionsViewModel(
- qsSceneAdapter = qsSceneAdapter,
+val Kosmos.lockscreenUserActionsViewModel by Fixture {
+ LockscreenUserActionsViewModel(
+ deviceEntryInteractor = deviceEntryInteractor,
+ communalInteractor = communalInteractor,
shadeInteractor = shadeInteractor,
)
}
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 851a378..457bd28 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
@@ -36,7 +36,7 @@
import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
import com.android.systemui.globalactions.domain.interactor.globalActionsInteractor
-import com.android.systemui.haptics.msdl.msdlPlayer
+import com.android.systemui.haptics.msdl.fakeMSDLPlayer
import com.android.systemui.haptics.qs.qsLongPressEffect
import com.android.systemui.jank.interactionJankMonitor
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
@@ -155,5 +155,5 @@
val scrimController by lazy { kosmos.scrimController }
val scrimStartable by lazy { kosmos.scrimStartable }
val sceneContainerOcclusionInteractor by lazy { kosmos.sceneContainerOcclusionInteractor }
- val msdlPlayer by lazy { kosmos.msdlPlayer }
+ val msdlPlayer by lazy { kosmos.fakeMSDLPlayer }
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/log/table/TableLogBufferFactoryKosmos.kt
similarity index 61%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/log/table/TableLogBufferFactoryKosmos.kt
index 128a7fc..c55dc6a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/log/table/TableLogBufferFactoryKosmos.kt
@@ -14,13 +14,18 @@
* limitations under the License.
*/
-package com.android.systemui.qs.ui.viewmodel
+package com.android.systemui.log.table
+import com.android.systemui.dump.dumpManager
import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.log.LogcatEchoTrackerAlways
+import com.android.systemui.util.time.fakeSystemClock
-val Kosmos.quickSettingsShadeSceneActionsViewModel: QuickSettingsShadeSceneActionsViewModel by
+val Kosmos.tableLogBufferFactory: TableLogBufferFactory by
Kosmos.Fixture {
- QuickSettingsShadeSceneActionsViewModel(
- quickSettingsContainerViewModel = quickSettingsContainerViewModel,
+ TableLogBufferFactory(
+ dumpManager = dumpManager,
+ systemClock = fakeSystemClock,
+ logcatEchoTracker = LogcatEchoTrackerAlways(),
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/log/table/TableLogBufferHelper.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/log/table/TableLogBufferHelper.kt
new file mode 100644
index 0000000..64c3974
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/log/table/TableLogBufferHelper.kt
@@ -0,0 +1,36 @@
+/*
+ * 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.log.table
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.log.LogcatEchoTrackerAlways
+import com.android.systemui.util.time.SystemClock
+import com.android.systemui.util.time.fakeSystemClock
+
+/**
+ * Creates a [TableLogBuffer] that will echo everything to logcat, which is useful for debugging
+ * tests.
+ */
+fun logcatTableLogBuffer(kosmos: Kosmos, name: String = "EchoToLogcatTableLogBuffer") =
+ logcatTableLogBuffer(kosmos.fakeSystemClock, name)
+
+/**
+ * Creates a [TableLogBuffer] that will echo everything to logcat, which is useful for debugging
+ * tests.
+ */
+fun logcatTableLogBuffer(systemClock: SystemClock, name: String = "EchoToLogcatTableLogBuffer") =
+ TableLogBuffer(maxSize = 50, name, systemClock, logcatEchoTracker = LogcatEchoTrackerAlways())
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderKosmos.kt
index a5690a0..cb7750f5 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderKosmos.kt
@@ -24,7 +24,6 @@
import com.android.systemui.kosmos.testScope
import com.android.systemui.media.controls.util.fakeMediaControllerFactory
import com.android.systemui.media.controls.util.mediaFlags
-import com.android.systemui.plugins.activityStarter
val Kosmos.mediaDataLoader by
Kosmos.Fixture {
@@ -32,7 +31,6 @@
testableContext,
testDispatcher,
testScope,
- activityStarter,
fakeMediaControllerFactory,
mediaFlags,
imageLoader,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorKosmos.kt
index 632436a..174e653 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorKosmos.kt
@@ -26,6 +26,7 @@
import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.media.controls.data.repository.mediaDataRepository
+import com.android.systemui.media.controls.shared.mediaLogger
import com.android.systemui.media.controls.shared.model.SmartspaceMediaDataProvider
import com.android.systemui.media.controls.util.fakeMediaControllerFactory
import com.android.systemui.media.controls.util.mediaFlags
@@ -60,5 +61,6 @@
keyguardUpdateMonitor = keyguardUpdateMonitor,
mediaDataRepository = mediaDataRepository,
mediaDataLoader = { mediaDataLoader },
+ mediaLogger = mediaLogger,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManagerKosmos.kt
index 11408d8..c479ce6 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManagerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaDeviceManagerKosmos.kt
@@ -41,6 +41,5 @@
},
fgExecutor = fakeExecutor,
bgExecutor = fakeExecutor,
- logger = mediaDeviceLogger,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerKosmos.kt
index b7660e0..b33edf9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerKosmos.kt
@@ -28,6 +28,8 @@
Kosmos.Fixture {
MediaTimeoutListener(
mediaControllerFactory = fakeMediaControllerFactory,
+ bgExecutor = fakeExecutor,
+ uiExecutor = fakeExecutor,
mainExecutor = fakeExecutor,
logger = MediaTimeoutLogger(logcatLogBuffer("MediaTimeoutLogBuffer")),
statusBarStateController = statusBarStateController,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/external/TileLifecycleManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/external/TileLifecycleManagerKosmos.kt
index a0fc76b..4978558 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/external/TileLifecycleManagerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/external/TileLifecycleManagerKosmos.kt
@@ -24,6 +24,7 @@
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.qs.tiles.impl.custom.packageManagerAdapterFacade
import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.time.fakeSystemClock
val Kosmos.tileLifecycleManagerFactory: TileLifecycleManager.Factory by
Kosmos.Fixture {
@@ -39,6 +40,7 @@
activityManager,
mock(),
fakeExecutor,
+ fakeSystemClock,
)
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModelKosmos.kt
similarity index 85%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelKosmos.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModelKosmos.kt
index 128a7fc..06592b1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModelKosmos.kt
@@ -18,9 +18,9 @@
import com.android.systemui.kosmos.Kosmos
-val Kosmos.quickSettingsShadeSceneActionsViewModel: QuickSettingsShadeSceneActionsViewModel by
+val Kosmos.quickSettingsShadeUserActionsViewModel: QuickSettingsShadeUserActionsViewModel by
Kosmos.Fixture {
- QuickSettingsShadeSceneActionsViewModel(
+ QuickSettingsShadeUserActionsViewModel(
quickSettingsContainerViewModel = quickSettingsContainerViewModel,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
index b3664e1..8744638 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
@@ -1,11 +1,20 @@
package com.android.systemui.scene
+import com.android.compose.animation.scene.ObservableTransitionState
+import com.android.systemui.classifier.domain.interactor.falsingInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.logger.sceneLogger
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.FakeOverlay
+import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
+import com.android.systemui.scene.ui.viewmodel.splitEdgeDetector
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import kotlinx.coroutines.flow.MutableStateFlow
var Kosmos.sceneKeys by Fixture {
listOf(
@@ -27,7 +36,9 @@
)
}
-val Kosmos.fakeOverlays by Fixture { overlayKeys.map { key -> FakeOverlay(key) }.toSet() }
+val Kosmos.fakeOverlaysByKeys by Fixture { overlayKeys.associateWith { FakeOverlay(it) } }
+
+val Kosmos.fakeOverlays by Fixture { fakeOverlaysByKeys.values.toSet() }
val Kosmos.overlays by Fixture { fakeOverlays }
@@ -49,3 +60,22 @@
navigationDistances = navigationDistances,
)
}
+
+val Kosmos.transitionState by Fixture {
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Idle(sceneContainerConfig.initialSceneKey)
+ )
+}
+
+val Kosmos.sceneContainerViewModel by Fixture {
+ SceneContainerViewModel(
+ sceneInteractor = sceneInteractor,
+ falsingInteractor = falsingInteractor,
+ powerInteractor = powerInteractor,
+ shadeInteractor = shadeInteractor,
+ splitEdgeDetector = splitEdgeDetector,
+ motionEventHandlerReceiver = {},
+ logger = sceneLogger
+ )
+ .apply { setTransitionState(transitionState) }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
index 53b6a2e..9a5698c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
@@ -24,8 +24,11 @@
import com.android.systemui.classifier.falsingCollector
import com.android.systemui.classifier.falsingManager
import com.android.systemui.deviceentry.domain.interactor.deviceEntryFaceAuthInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryHapticsInteractor
import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
+import com.android.systemui.haptics.msdl.msdlPlayer
+import com.android.systemui.haptics.vibratorHelper
import com.android.systemui.keyguard.dismissCallbackRegistry
import com.android.systemui.keyguard.domain.interactor.keyguardEnabledInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
@@ -55,6 +58,7 @@
applicationScope = testScope.backgroundScope,
sceneInteractor = sceneInteractor,
deviceEntryInteractor = deviceEntryInteractor,
+ deviceEntryHapticsInteractor = deviceEntryHapticsInteractor,
deviceUnlockedInteractor = deviceUnlockedInteractor,
bouncerInteractor = bouncerInteractor,
keyguardInteractor = keyguardInteractor,
@@ -82,5 +86,7 @@
dismissCallbackRegistry = dismissCallbackRegistry,
statusBarStateController = sysuiStatusBarStateController,
alternateBouncerInteractor = alternateBouncerInteractor,
+ vibratorHelper = vibratorHelper,
+ msdlPlayer = msdlPlayer,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorKosmos.kt
similarity index 67%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorKosmos.kt
index 128a7fc..e0b5292 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorKosmos.kt
@@ -14,13 +14,16 @@
* limitations under the License.
*/
-package com.android.systemui.qs.ui.viewmodel
+package com.android.systemui.scene.ui.viewmodel
+import androidx.compose.ui.unit.dp
import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.shade.domain.interactor.shadeInteractor
-val Kosmos.quickSettingsShadeSceneActionsViewModel: QuickSettingsShadeSceneActionsViewModel by
+var Kosmos.splitEdgeDetector: SplitEdgeDetector by
Kosmos.Fixture {
- QuickSettingsShadeSceneActionsViewModel(
- quickSettingsContainerViewModel = quickSettingsContainerViewModel,
+ SplitEdgeDetector(
+ topEdgeSplitFraction = shadeInteractor::getTopEdgeSplitFraction,
+ edgeSize = 40.dp,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeSceneActionsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeUserActionsViewModelKosmos.kt
similarity index 81%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeSceneActionsViewModelKosmos.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeUserActionsViewModelKosmos.kt
index f792ab9..6345c40 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeSceneActionsViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeUserActionsViewModelKosmos.kt
@@ -18,7 +18,7 @@
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
-import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeSceneActionsViewModel
+import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeUserActionsViewModel
-val Kosmos.notificationsShadeSceneActionsViewModel:
- NotificationsShadeSceneActionsViewModel by Fixture { NotificationsShadeSceneActionsViewModel() }
+val Kosmos.notificationsShadeUserActionsViewModel:
+ NotificationsShadeUserActionsViewModel by Fixture { NotificationsShadeUserActionsViewModel() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeWindowModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeWindowModelKosmos.kt
index 4b42e07..9742595 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeWindowModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeWindowModelKosmos.kt
@@ -16,12 +16,18 @@
package com.android.systemui.shade.ui.viewmodel
+import com.android.systemui.authentication.domain.interactor.authenticationInteractor
+import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.scene.domain.interactor.sceneInteractor
val Kosmos.notificationShadeWindowModel: NotificationShadeWindowModel by
Kosmos.Fixture {
NotificationShadeWindowModel(
keyguardTransitionInteractor,
+ sceneInteractor = { sceneInteractor },
+ authenticationInteractor = { authenticationInteractor },
+ primaryBouncerInteractor = primaryBouncerInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelKosmos.kt
similarity index 89%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelKosmos.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelKosmos.kt
index 2387aa8..48c5121 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelKosmos.kt
@@ -21,8 +21,8 @@
import com.android.systemui.qs.ui.adapter.qsSceneAdapter
import com.android.systemui.shade.domain.interactor.shadeInteractor
-val Kosmos.shadeSceneActionsViewModel: ShadeSceneActionsViewModel by Fixture {
- ShadeSceneActionsViewModel(
+val Kosmos.shadeUserActionsViewModel: ShadeUserActionsViewModel by Fixture {
+ ShadeUserActionsViewModel(
qsSceneAdapter = qsSceneAdapter,
shadeInteractor = shadeInteractor,
)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorKosmos.kt
index 386c7c5..d76defe 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorKosmos.kt
@@ -18,7 +18,7 @@
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
-import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
val Kosmos.airplaneModeInteractor: AirplaneModeInteractor by
@@ -26,6 +26,6 @@
AirplaneModeInteractor(
FakeAirplaneModeRepository(),
FakeConnectivityRepository(),
- FakeMobileConnectionsRepository(),
+ fakeMobileConnectionsRepository,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt
index e7be639..de73d33 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionsRepository.kt
@@ -26,14 +26,13 @@
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
-import com.android.systemui.util.mockito.mock
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
// TODO(b/261632894): remove this in favor of the real impl or DemoMobileConnectionsRepository
class FakeMobileConnectionsRepository(
mobileMappings: MobileMappingsProxy = FakeMobileMappingsProxy(),
- val tableLogBuffer: TableLogBuffer = mock<TableLogBuffer> {},
+ val tableLogBuffer: TableLogBuffer,
) : MobileConnectionsRepository {
val GSM_KEY = mobileMappings.toIconKey(GSM)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepositoryKosmos.kt
index 9d62ea5..cd22f1d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionsRepositoryKosmos.kt
@@ -18,10 +18,12 @@
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
-import com.android.systemui.util.mockito.mock
+import com.android.systemui.log.table.logcatTableLogBuffer
val Kosmos.fakeMobileConnectionsRepository by Fixture {
- FakeMobileConnectionsRepository(tableLogBuffer = mock())
+ FakeMobileConnectionsRepository(
+ tableLogBuffer = logcatTableLogBuffer(this, "FakeMobileConnectionsRepository"),
+ )
}
val Kosmos.mobileConnectionsRepository by
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/user/utils/FakeUserScopedService.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/user/utils/FakeUserScopedService.kt
new file mode 100644
index 0000000..78763f9
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/user/utils/FakeUserScopedService.kt
@@ -0,0 +1,33 @@
+/*
+ * 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.user.utils
+
+import android.os.UserHandle
+
+class FakeUserScopedService<T>(private val defaultImplementation: T) : UserScopedService<T> {
+
+ private val implementations = mutableMapOf<UserHandle, T>()
+
+ fun addImplementation(user: UserHandle, implementation: T) {
+ implementations[user] = implementation
+ }
+
+ fun removeImplementation(user: UserHandle): T? = implementations.remove(user)
+
+ override fun forUser(user: UserHandle): T =
+ implementations.getOrDefault(user, defaultImplementation)
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/view/accessibility/data/repository/FakeCaptioningRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/view/accessibility/data/repository/FakeCaptioningRepository.kt
deleted file mode 100644
index 663aaf2..0000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/view/accessibility/data/repository/FakeCaptioningRepository.kt
+++ /dev/null
@@ -1,41 +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.systemui.view.accessibility.data.repository
-
-import com.android.settingslib.view.accessibility.data.repository.CaptioningRepository
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
-
-class FakeCaptioningRepository : CaptioningRepository {
-
- private val mutableIsSystemAudioCaptioningEnabled = MutableStateFlow(false)
- override val isSystemAudioCaptioningEnabled: StateFlow<Boolean>
- get() = mutableIsSystemAudioCaptioningEnabled.asStateFlow()
-
- private val mutableIsSystemAudioCaptioningUiEnabled = MutableStateFlow(false)
- override val isSystemAudioCaptioningUiEnabled: StateFlow<Boolean>
- get() = mutableIsSystemAudioCaptioningUiEnabled.asStateFlow()
-
- override suspend fun setIsSystemAudioCaptioningEnabled(isEnabled: Boolean) {
- mutableIsSystemAudioCaptioningEnabled.value = isEnabled
- }
-
- fun setIsSystemAudioCaptioningUiEnabled(isSystemAudioCaptioningUiEnabled: Boolean) {
- mutableIsSystemAudioCaptioningUiEnabled.value = isSystemAudioCaptioningUiEnabled
- }
-}
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 1fa6c3f..888351f 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
@@ -33,6 +33,12 @@
class FakeAudioRepository : AudioRepository {
+ private val unMutableStreams =
+ setOf(
+ AudioManager.STREAM_VOICE_CALL,
+ AudioManager.STREAM_ALARM,
+ )
+
private val mutableMode = MutableStateFlow(AudioManager.MODE_NORMAL)
override val mode: StateFlow<Int> = mutableMode.asStateFlow()
@@ -73,7 +79,7 @@
volume = 0,
minVolume = 0,
maxVolume = 10,
- isAffectedByMute = false,
+ isAffectedByMute = audioStream.value !in unMutableStreams,
isAffectedByRingerMode = false,
isMuted = false,
)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/captioning/CaptioningModuleKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/captioning/CaptioningModuleKosmos.kt
index e7162d2..6d30c68 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/captioning/CaptioningModuleKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/captioning/CaptioningModuleKosmos.kt
@@ -17,9 +17,9 @@
package com.android.systemui.volume.panel.component.captioning
import com.android.internal.logging.uiEventLogger
+import com.android.systemui.accessibility.domain.interactor.captioningInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
-import com.android.systemui.view.accessibility.data.repository.captioningInteractor
import com.android.systemui.volume.panel.component.button.ui.composable.ToggleButtonComponent
import com.android.systemui.volume.panel.component.captioning.domain.CaptioningAvailabilityCriteria
import com.android.systemui.volume.panel.component.captioning.ui.viewmodel.captioningViewModel
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModelKosmos.kt
index 0edd9e0..e23a21a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/captioning/ui/viewmodel/CaptioningViewModelKosmos.kt
@@ -18,9 +18,9 @@
import android.content.applicationContext
import com.android.internal.logging.uiEventLogger
+import com.android.systemui.accessibility.domain.interactor.captioningInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
-import com.android.systemui.view.accessibility.data.repository.captioningInteractor
val Kosmos.captioningViewModel by
Kosmos.Fixture {
diff --git a/packages/SystemUI/tests/utils/src/com/android/telecom/TelecomManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/telecom/TelecomManagerKosmos.kt
index 4e0c0883..d1bee61 100644
--- a/packages/SystemUI/tests/utils/src/com/android/telecom/TelecomManagerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/telecom/TelecomManagerKosmos.kt
@@ -21,4 +21,5 @@
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.util.mockito.mock
-var Kosmos.telecomManager by Fixture<TelecomManager?> { mock() }
+val Kosmos.mockTelecomManager by Fixture<TelecomManager> { mock() }
+var Kosmos.telecomManager by Fixture<TelecomManager?> { mockTelecomManager }
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index 9b0c8e5..333fe4c 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -127,6 +127,7 @@
libs: [
"framework-minus-apex.ravenwood",
"ravenwood-junit",
+ "ravenwood-helper-libcore-runtime",
],
visibility: ["//visibility:private"],
}
diff --git a/ravenwood/OWNERS b/ravenwood/OWNERS
index badfca0..f7b13d1 100644
--- a/ravenwood/OWNERS
+++ b/ravenwood/OWNERS
@@ -1,8 +1,8 @@
set noparent
-jsharkey@google.com
-omakoto@google.com
-dplotnikov@google.com
+topjohnwu@google.com
+hackbod@google.com #{LAST_RESORT_SUGGESTION}
+
per-file ravenwood-annotation-allowed-classes.txt = dplotnikov@google.com
per-file texts/ravenwood-annotation-allowed-classes.txt = dplotnikov@google.com
diff --git a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodNativeSubstitutionClass.java b/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodRedirect.java
similarity index 82%
copy from ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodNativeSubstitutionClass.java
copy to ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodRedirect.java
index 4b9cf85..b582ccf 100644
--- a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodNativeSubstitutionClass.java
+++ b/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodRedirect.java
@@ -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.
@@ -15,7 +15,7 @@
*/
package android.ravenwood.annotation;
-import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.ElementType.METHOD;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -29,8 +29,7 @@
*
* @hide
*/
-@Target({TYPE})
+@Target({METHOD})
@Retention(RetentionPolicy.CLASS)
-public @interface RavenwoodNativeSubstitutionClass {
- String value();
+public @interface RavenwoodRedirect {
}
diff --git a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodNativeSubstitutionClass.java b/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodRedirectionClass.java
similarity index 94%
rename from ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodNativeSubstitutionClass.java
rename to ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodRedirectionClass.java
index 4b9cf85..bee9222 100644
--- a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodNativeSubstitutionClass.java
+++ b/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodRedirectionClass.java
@@ -31,6 +31,6 @@
*/
@Target({TYPE})
@Retention(RetentionPolicy.CLASS)
-public @interface RavenwoodNativeSubstitutionClass {
+public @interface RavenwoodRedirectionClass {
String value();
}
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java
index f237ba9..1d182da 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java
@@ -27,6 +27,9 @@
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.internal.os.RuntimeInit;
+import com.android.ravenwood.common.RavenwoodCommonUtils;
+
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runners.model.TestClass;
@@ -35,7 +38,7 @@
* Provide hook points created by {@link RavenwoodAwareTestRunner}.
*/
public class RavenwoodAwareTestRunnerHook {
- private static final String TAG = "RavenwoodAwareTestRunnerHook";
+ private static final String TAG = RavenwoodAwareTestRunner.TAG;
private RavenwoodAwareTestRunnerHook() {
}
@@ -56,20 +59,36 @@
* Called when a runner starts, before the inner runner gets a chance to run.
*/
public static void onRunnerInitializing(Runner runner, TestClass testClass) {
+ // TODO: Move the initialization code to a better place.
+
+ initOnce();
+
// This log call also ensures the framework JNI is loaded.
Log.i(TAG, "onRunnerInitializing: testClass=" + testClass.getJavaClass()
+ " runner=" + runner);
- // TODO: Move the initialization code to a better place.
+ // This is needed to make AndroidJUnit4ClassRunner happy.
+ InstrumentationRegistry.registerInstance(null, Bundle.EMPTY);
+ }
+
+ private static boolean sInitialized = false;
+
+ private static void initOnce() {
+ if (sInitialized) {
+ return;
+ }
+ sInitialized = true;
+
+ // We haven't initialized liblog yet, so directly write to System.out here.
+ RavenwoodCommonUtils.log(TAG, "initOnce()");
+
+ // Redirect stdout/stdin to liblog.
+ RuntimeInit.redirectLogStreams();
// This will let AndroidJUnit4 use the original runner.
System.setProperty("android.junit.runner",
"androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner");
System.setProperty(RAVENWOOD_VERSION_JAVA_SYSPROP, "1");
-
-
- // This is needed to make AndroidJUnit4ClassRunner happy.
- InstrumentationRegistry.registerInstance(null, Bundle.EMPTY);
}
/**
@@ -87,7 +106,7 @@
*/
public static boolean onBefore(RavenwoodAwareTestRunner runner, Description description,
Scope scope, Order order) {
- Log.i(TAG, "onBefore: description=" + description + ", " + scope + ", " + order);
+ Log.v(TAG, "onBefore: description=" + description + ", " + scope + ", " + order);
if (scope == Scope.Class && order == Order.First) {
// Keep track of the current class.
@@ -113,7 +132,7 @@
*/
public static boolean onAfter(RavenwoodAwareTestRunner runner, Description description,
Scope scope, Order order, Throwable th) {
- Log.i(TAG, "onAfter: description=" + description + ", " + scope + ", " + order + ", " + th);
+ Log.v(TAG, "onAfter: description=" + description + ", " + scope + ", " + order + ", " + th);
if (scope == Scope.Instance && order == Order.First) {
getStats().onTestFinished(sCurrentClassDescription, description,
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
index a2088fd..0059360 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
@@ -36,7 +36,6 @@
import androidx.test.platform.app.InstrumentationRegistry;
-import com.android.internal.os.RuntimeInit;
import com.android.server.LocalServices;
import org.junit.runner.Description;
@@ -92,8 +91,6 @@
Thread.setDefaultUncaughtExceptionHandler(sUncaughtExceptionHandler);
}
- RuntimeInit.redirectLogStreams();
-
android.os.Process.init$ravenwood(rule.mUid, rule.mPid);
android.os.Binder.init$ravenwood();
setSystemProperties(rule.mSystemProperties);
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
index 7a160955..bfde9cb 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
@@ -23,7 +23,6 @@
import android.util.Log;
-import com.android.ravenwood.common.RavenwoodCommonUtils;
import com.android.ravenwood.common.SneakyThrow;
import org.junit.Assume;
@@ -75,7 +74,7 @@
* (no hooks, etc.)
*/
public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orderable {
- private static final String TAG = "RavenwoodAwareTestRunner";
+ public static final String TAG = "Ravenwood";
@Inherited
@Target({TYPE})
@@ -142,16 +141,9 @@
private Description mDescription = null;
private Throwable mExceptionInConstructor = null;
- /** Simple logging method. */
- private void log(String message) {
- RavenwoodCommonUtils.log(TAG, "[" + getTestClass().getJavaClass() + " @" + this + "] "
- + message);
- }
-
- private Error logAndFail(String message, Throwable innerException) {
- log(message);
- log(" Exception=" + innerException);
- throw new AssertionError(message, innerException);
+ private Error logAndFail(String message, Throwable exception) {
+ Log.e(TAG, message, exception);
+ throw new AssertionError(message, exception);
}
public TestClass getTestClass() {
@@ -165,6 +157,8 @@
try {
mTestClass = new TestClass(testClass);
+ onRunnerInitializing();
+
/*
* If the class has @DisabledOnRavenwood, then we'll delegate to
* ClassSkippingTestRunner, which simply skips it.
@@ -186,10 +180,8 @@
realRunnerClass = BlockJUnit4ClassRunner.class;
}
- onRunnerInitializing();
-
try {
- log("Initializing the inner runner: " + realRunnerClass);
+ Log.i(TAG, "Initializing the inner runner: " + realRunnerClass);
mRealRunner = instantiateRealRunner(realRunnerClass, testClass);
mDescription = mRealRunner.getDescription();
@@ -201,12 +193,7 @@
} catch (Throwable th) {
// If we throw in the constructor, Tradefed may not report it and just ignore the class,
// so record it and throw it when the test actually started.
- log("Fatal: Exception detected in constructor: " + th.getMessage() + "\n"
- + Log.getStackTraceString(th));
- if (true) {
- // TODO(b/363094647) Remove this
- throw th;
- }
+ Log.e(TAG, "Fatal: Exception detected in constructor", th);
mExceptionInConstructor = new RuntimeException("Exception detected in constructor",
th);
mDescription = Description.createTestDescription(testClass, "Constructor");
@@ -240,8 +227,7 @@
if (!isOnRavenwood()) {
return;
}
-
- log("onRunnerInitializing");
+ // DO NOT USE android.util.Log before calling onRunnerInitializing().
RavenwoodAwareTestRunnerHook.onRunnerInitializing(this, mTestClass);
@@ -254,7 +240,7 @@
if (!isOnRavenwood()) {
return;
}
- log("runAnnotatedMethodsOnRavenwood() " + annotationClass.getName());
+ Log.v(TAG, "runAnnotatedMethodsOnRavenwood() " + annotationClass.getName());
for (var method : getTestClass().getAnnotatedMethods(annotationClass)) {
ensureIsPublicVoidMethod(method.getMethod(), /* isStatic=*/ instance == null);
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/CursorWindow_host.java b/ravenwood/runtime-helper-src/framework/android/database/CursorWindow_host.java
similarity index 89%
rename from ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/CursorWindow_host.java
rename to ravenwood/runtime-helper-src/framework/android/database/CursorWindow_host.java
index f38d565..e21a9cd 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/CursorWindow_host.java
+++ b/ravenwood/runtime-helper-src/framework/android/database/CursorWindow_host.java
@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.platform.test.ravenwood.nativesubstitution;
+package android.database;
-import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.os.Parcel;
import android.util.Base64;
@@ -35,8 +34,8 @@
private String mName;
private int mColumnNum;
private static class Row {
- String[] fields;
- int[] types;
+ String[] mFields;
+ int[] mTypes;
}
private final List<Row> mRows = new ArrayList<>();
@@ -69,9 +68,9 @@
public static boolean nativeAllocRow(long windowPtr) {
CursorWindow_host instance = sInstances.get(windowPtr);
Row row = new Row();
- row.fields = new String[instance.mColumnNum];
- row.types = new int[instance.mColumnNum];
- Arrays.fill(row.types, Cursor.FIELD_TYPE_NULL);
+ row.mFields = new String[instance.mColumnNum];
+ row.mTypes = new int[instance.mColumnNum];
+ Arrays.fill(row.mTypes, Cursor.FIELD_TYPE_NULL);
instance.mRows.add(row);
return true;
}
@@ -82,8 +81,8 @@
return false;
}
Row r = instance.mRows.get(row);
- r.fields[column] = value;
- r.types[column] = type;
+ r.mFields[column] = value;
+ r.mTypes[column] = type;
return true;
}
@@ -93,7 +92,7 @@
return Cursor.FIELD_TYPE_NULL;
}
- return instance.mRows.get(row).types[column];
+ return instance.mRows.get(row).mTypes[column];
}
public static boolean nativePutString(long windowPtr, String value,
@@ -107,7 +106,7 @@
return null;
}
- return instance.mRows.get(row).fields[column];
+ return instance.mRows.get(row).mFields[column];
}
public static boolean nativePutLong(long windowPtr, long value, int row, int column) {
@@ -170,8 +169,8 @@
parcel.writeInt(window.mColumnNum);
parcel.writeInt(window.mRows.size());
for (int row = 0; row < window.mRows.size(); row++) {
- parcel.writeStringArray(window.mRows.get(row).fields);
- parcel.writeIntArray(window.mRows.get(row).types);
+ parcel.writeStringArray(window.mRows.get(row).mFields);
+ parcel.writeIntArray(window.mRows.get(row).mTypes);
}
}
@@ -183,8 +182,8 @@
int rowCount = parcel.readInt();
for (int row = 0; row < rowCount; row++) {
Row r = new Row();
- r.fields = parcel.createStringArray();
- r.types = parcel.createIntArray();
+ r.mFields = parcel.createStringArray();
+ r.mTypes = parcel.createIntArray();
window.mRows.add(r);
}
return windowPtr;
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/MessageQueue_host.java b/ravenwood/runtime-helper-src/framework/android/os/MessageQueue_host.java
similarity index 97%
rename from ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/MessageQueue_host.java
rename to ravenwood/runtime-helper-src/framework/android/os/MessageQueue_host.java
index 5e81124..1b63adc 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/MessageQueue_host.java
+++ b/ravenwood/runtime-helper-src/framework/android/os/MessageQueue_host.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.platform.test.ravenwood.nativesubstitution;
+package android.os;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Parcel_host.java b/ravenwood/runtime-helper-src/framework/android/os/Parcel_host.java
similarity index 99%
rename from ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Parcel_host.java
rename to ravenwood/runtime-helper-src/framework/android/os/Parcel_host.java
index cb00b3e..720f1d2 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Parcel_host.java
+++ b/ravenwood/runtime-helper-src/framework/android/os/Parcel_host.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.platform.test.ravenwood.nativesubstitution;
+package android.os;
import android.system.ErrnoException;
import android.system.Os;
@@ -527,4 +527,4 @@
}
return false;
}
-}
\ No newline at end of file
+}
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/SystemProperties_host.java b/ravenwood/runtime-helper-src/framework/android/os/SystemProperties_host.java
similarity index 89%
rename from ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/SystemProperties_host.java
rename to ravenwood/runtime-helper-src/framework/android/os/SystemProperties_host.java
index e7479d3..b09bf31 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/SystemProperties_host.java
+++ b/ravenwood/runtime-helper-src/framework/android/os/SystemProperties_host.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.platform.test.ravenwood.nativesubstitution;
+package android.os;
import android.util.SparseArray;
@@ -36,9 +36,6 @@
/** Predicate tested to determine if a given key can be written. */
@GuardedBy("sLock")
private static Predicate<String> sKeyWritablePredicate;
- /** Callback to trigger when values are changed */
- @GuardedBy("sLock")
- private static Runnable sChangeCallback;
/**
* Reverse mapping that provides a way back to an original key from the
@@ -48,7 +45,7 @@
private static SparseArray<String> sKeyHandles = new SparseArray<>();
/**
- * Basically the same as {@link #native_init$ravenwood}, but it'll only run if no values are
+ * Basically the same as {@link #init$ravenwood}, but it'll only run if no values are
* set yet.
*/
public static void initializeIfNeeded(Map<String, String> values,
@@ -57,30 +54,32 @@
if (sValues != null) {
return; // Already initialized.
}
- native_init$ravenwood(values, keyReadablePredicate, keyWritablePredicate,
- () -> {});
+ init$ravenwood(values, keyReadablePredicate, keyWritablePredicate);
}
}
- public static void native_init$ravenwood(Map<String, String> values,
- Predicate<String> keyReadablePredicate, Predicate<String> keyWritablePredicate,
- Runnable changeCallback) {
+ public static void init$ravenwood(Map<String, String> values,
+ Predicate<String> keyReadablePredicate, Predicate<String> keyWritablePredicate) {
synchronized (sLock) {
sValues = Objects.requireNonNull(values);
sKeyReadablePredicate = Objects.requireNonNull(keyReadablePredicate);
sKeyWritablePredicate = Objects.requireNonNull(keyWritablePredicate);
- sChangeCallback = Objects.requireNonNull(changeCallback);
sKeyHandles.clear();
+ synchronized (SystemProperties.sChangeCallbacks) {
+ SystemProperties.sChangeCallbacks.clear();
+ }
}
}
- public static void native_reset$ravenwood() {
+ public static void reset$ravenwood() {
synchronized (sLock) {
sValues = null;
sKeyReadablePredicate = null;
sKeyWritablePredicate = null;
- sChangeCallback = null;
sKeyHandles.clear();
+ synchronized (SystemProperties.sChangeCallbacks) {
+ SystemProperties.sChangeCallbacks.clear();
+ }
}
}
@@ -101,7 +100,7 @@
} else {
sValues.put(key, val);
}
- sChangeCallback.run();
+ SystemProperties.callChangeCallbacks();
}
}
@@ -183,7 +182,7 @@
// Report through callback always registered via init above
synchronized (sLock) {
Preconditions.requireNonNullViaRavenwoodRule(sValues);
- sChangeCallback.run();
+ SystemProperties.callChangeCallbacks();
}
}
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/EventLog_host.java b/ravenwood/runtime-helper-src/framework/android/util/EventLog_host.java
similarity index 83%
rename from ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/EventLog_host.java
rename to ravenwood/runtime-helper-src/framework/android/util/EventLog_host.java
index 55d4ffb..878a0ff 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/EventLog_host.java
+++ b/ravenwood/runtime-helper-src/framework/android/util/EventLog_host.java
@@ -13,12 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.platform.test.ravenwood.nativesubstitution;
+package android.util;
import com.android.internal.os.RuntimeInit;
import java.io.PrintStream;
-import java.util.Collection;
public class EventLog_host {
public static int writeEvent(int tag, int value) {
@@ -58,15 +57,6 @@
return sb.length();
}
- public static void readEvents(int[] tags, Collection<android.util.EventLog.Event> output) {
- throw new UnsupportedOperationException();
- }
-
- public static void readEventsOnWrapping(int[] tags, long timestamp,
- Collection<android.util.EventLog.Event> output) {
- throw new UnsupportedOperationException();
- }
-
/**
* Return the "real" {@code System.out} if it's been swapped by {@code RavenwoodRuleImpl}, so
* that we don't end up in a recursive loop.
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Log_host.java b/ravenwood/runtime-helper-src/framework/android/util/Log_host.java
similarity index 95%
rename from ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Log_host.java
rename to ravenwood/runtime-helper-src/framework/android/util/Log_host.java
index f301b9c..d232ef2 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/Log_host.java
+++ b/ravenwood/runtime-helper-src/framework/android/util/Log_host.java
@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.platform.test.ravenwood.nativesubstitution;
+package android.util;
-import android.util.Log;
import android.util.Log.Level;
import com.android.internal.os.RuntimeInit;
@@ -44,7 +43,7 @@
case Log.LOG_ID_SYSTEM: buffer = "system"; break;
case Log.LOG_ID_CRASH: buffer = "crash"; break;
default: buffer = "buf:" + bufID; break;
- };
+ }
final String prio;
switch (priority) {
@@ -55,7 +54,7 @@
case Log.ERROR: prio = "E"; break;
case Log.ASSERT: prio = "A"; break;
default: prio = "prio:" + priority; break;
- };
+ }
for (String s : msg.split("\\n")) {
getRealOut().println(String.format("logd: [%s] %s %s: %s", buffer, prio, tag, s));
diff --git a/ravenwood/runtime-helper-src/framework/com/android/internal/os/LongArrayContainer_host.java b/ravenwood/runtime-helper-src/framework/com/android/internal/os/LongArrayContainer_host.java
new file mode 100644
index 0000000..c18c307
--- /dev/null
+++ b/ravenwood/runtime-helper-src/framework/com/android/internal/os/LongArrayContainer_host.java
@@ -0,0 +1,63 @@
+/*
+ * 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.os;
+
+import java.util.Arrays;
+import java.util.HashMap;
+
+public class LongArrayContainer_host {
+ private static final HashMap<Long, long[]> sInstances = new HashMap<>();
+ private static long sNextId = 1;
+
+ public static long native_init(int arrayLength) {
+ long[] array = new long[arrayLength];
+ long instanceId = sNextId++;
+ sInstances.put(instanceId, array);
+ return instanceId;
+ }
+
+ static long[] getInstance(long instanceId) {
+ return sInstances.get(instanceId);
+ }
+
+ public static void native_setValues(long instanceId, long[] values) {
+ System.arraycopy(values, 0, getInstance(instanceId), 0, values.length);
+ }
+
+ public static void native_getValues(long instanceId, long[] values) {
+ System.arraycopy(getInstance(instanceId), 0, values, 0, values.length);
+ }
+
+ public static boolean native_combineValues(long instanceId, long[] array, int[] indexMap) {
+ long[] values = getInstance(instanceId);
+
+ boolean nonZero = false;
+ Arrays.fill(array, 0);
+
+ for (int i = 0; i < values.length; i++) {
+ int index = indexMap[i];
+ if (index < 0 || index >= array.length) {
+ throw new IndexOutOfBoundsException("Index " + index + " is out of bounds: [0, "
+ + (array.length - 1) + "]");
+ }
+ if (values[i] != 0) {
+ array[index] += values[i];
+ nonZero = true;
+ }
+ }
+ return nonZero;
+ }
+}
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/LongArrayMultiStateCounter_host.java b/ravenwood/runtime-helper-src/framework/com/android/internal/os/LongArrayMultiStateCounter_host.java
similarity index 87%
rename from ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/LongArrayMultiStateCounter_host.java
rename to ravenwood/runtime-helper-src/framework/com/android/internal/os/LongArrayMultiStateCounter_host.java
index 0f65544..9ce8ea8 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/LongArrayMultiStateCounter_host.java
+++ b/ravenwood/runtime-helper-src/framework/com/android/internal/os/LongArrayMultiStateCounter_host.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.platform.test.ravenwood.nativesubstitution;
+package com.android.internal.os;
import android.os.BadParcelableException;
import android.os.Parcel;
@@ -28,7 +28,7 @@
public class LongArrayMultiStateCounter_host {
/**
- * A reimplementation of {@link com.android.internal.os.LongArrayMultiStateCounter}, only in
+ * A reimplementation of {@link LongArrayMultiStateCounter}, only in
* Java instead of native. The majority of the code (in C++) can be found in
* /frameworks/native/libs/battery/MultiStateCounter.h
*/
@@ -257,50 +257,6 @@
}
}
- public static class LongArrayContainer_host {
- private static final HashMap<Long, long[]> sInstances = new HashMap<>();
- private static long sNextId = 1;
-
- public static long native_init(int arrayLength) {
- long[] array = new long[arrayLength];
- long instanceId = sNextId++;
- sInstances.put(instanceId, array);
- return instanceId;
- }
-
- static long[] getInstance(long instanceId) {
- return sInstances.get(instanceId);
- }
-
- public static void native_setValues(long instanceId, long[] values) {
- System.arraycopy(values, 0, getInstance(instanceId), 0, values.length);
- }
-
- public static void native_getValues(long instanceId, long[] values) {
- System.arraycopy(getInstance(instanceId), 0, values, 0, values.length);
- }
-
- public static boolean native_combineValues(long instanceId, long[] array, int[] indexMap) {
- long[] values = getInstance(instanceId);
-
- boolean nonZero = false;
- Arrays.fill(array, 0);
-
- for (int i = 0; i < values.length; i++) {
- int index = indexMap[i];
- if (index < 0 || index >= array.length) {
- throw new IndexOutOfBoundsException("Index " + index + " is out of bounds: [0, "
- + (array.length - 1) + "]");
- }
- if (values[i] != 0) {
- array[index] += values[i];
- nonZero = true;
- }
- }
- return nonZero;
- }
- }
-
private static final HashMap<Long, LongArrayMultiStateCounterRavenwood> sInstances =
new HashMap<>();
private static long sNextId = 1;
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/LongMultiStateCounter_host.java b/ravenwood/runtime-helper-src/framework/com/android/internal/os/LongMultiStateCounter_host.java
similarity index 98%
rename from ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/LongMultiStateCounter_host.java
rename to ravenwood/runtime-helper-src/framework/com/android/internal/os/LongMultiStateCounter_host.java
index 9486651..1d95aa1 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/LongMultiStateCounter_host.java
+++ b/ravenwood/runtime-helper-src/framework/com/android/internal/os/LongMultiStateCounter_host.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.platform.test.ravenwood.nativesubstitution;
+package com.android.internal.os;
import android.os.BadParcelableException;
import android.os.Parcel;
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/RavenwoodEnvironment_host.java b/ravenwood/runtime-helper-src/framework/com/android/internal/ravenwood/RavenwoodEnvironment_host.java
similarity index 94%
rename from ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/RavenwoodEnvironment_host.java
rename to ravenwood/runtime-helper-src/framework/com/android/internal/ravenwood/RavenwoodEnvironment_host.java
index f894b0e..3bf116d 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/nativesubstitution/RavenwoodEnvironment_host.java
+++ b/ravenwood/runtime-helper-src/framework/com/android/internal/ravenwood/RavenwoodEnvironment_host.java
@@ -13,12 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.platform.test.ravenwood.nativesubstitution;
+package com.android.internal.ravenwood;
+import android.os.SystemProperties_host;
import android.platform.test.ravenwood.RavenwoodSystemProperties;
import android.util.Log;
-import com.android.internal.ravenwood.RavenwoodEnvironment;
import com.android.ravenwood.common.JvmWorkaround;
import com.android.ravenwood.common.RavenwoodCommonUtils;
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java
index 0f955e7..c519204 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java
+++ b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java
@@ -15,6 +15,9 @@
*/
package com.android.platform.test.ravenwood.runtimehelper;
+import android.system.ErrnoException;
+import android.system.Os;
+
import com.android.ravenwood.common.RavenwoodCommonUtils;
import java.io.File;
@@ -37,6 +40,14 @@
private static final boolean SKIP_LOADING_LIBANDROID = "1".equals(System.getenv(
"RAVENWOOD_SKIP_LOADING_LIBANDROID"));
+ /**
+ * If set to 1, and if $ANDROID_LOG_TAGS isn't set, we enable the verbose logging.
+ *
+ * (See also InitLogging() in http://ac/system/libbase/logging.cpp)
+ */
+ private static final boolean RAVENWOOD_VERBOSE_LOGGING = "1".equals(System.getenv(
+ "RAVENWOOD_VERBOSE"));
+
public static final String CORE_NATIVE_CLASSES = "core_native_classes";
public static final String ICU_DATA_PATH = "icu.data.path";
public static final String KEYBOARD_PATHS = "keyboard_paths";
@@ -123,6 +134,15 @@
return;
}
+ if (RAVENWOOD_VERBOSE_LOGGING) {
+ log("Force enabling verbose logging");
+ try {
+ Os.setenv("ANDROID_LOG_TAGS", "*:v", true);
+ } catch (ErrnoException e) {
+ // Shouldn't happen.
+ }
+ }
+
// Make sure these properties are not set.
ensurePropertyNotSet(CORE_NATIVE_CLASSES);
ensurePropertyNotSet(ICU_DATA_PATH);
diff --git a/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java b/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java
index a5c0b54..c94ef31 100644
--- a/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java
+++ b/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java
@@ -93,4 +93,8 @@
throw new ErrnoException("pread", OsConstants.EIO, e);
}
}
+
+ public static void setenv(String name, String value, boolean overwrite) throws ErrnoException {
+ RavenwoodRuntimeNative.setenv(name, value, overwrite);
+ }
}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java
index 0d8408c..ad80d92 100644
--- a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java
+++ b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java
@@ -53,6 +53,9 @@
private static native int nOpen(String path, int flags, int mode) throws ErrnoException;
+ public static native void setenv(String name, String value, boolean overwrite)
+ throws ErrnoException;
+
public static long lseek(FileDescriptor fd, long offset, int whence) throws ErrnoException {
return nLseek(JvmWorkaround.getInstance().getFdInt(fd), offset, whence);
}
diff --git a/ravenwood/runtime-jni/ravenwood_runtime.cpp b/ravenwood/runtime-jni/ravenwood_runtime.cpp
index f5cb019f..c255be5 100644
--- a/ravenwood/runtime-jni/ravenwood_runtime.cpp
+++ b/ravenwood/runtime-jni/ravenwood_runtime.cpp
@@ -214,6 +214,19 @@
return throwIfMinusOne(env, "open", TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode)));
}
+static void Linux_setenv(JNIEnv* env, jobject, jstring javaName, jstring javaValue,
+ jboolean overwrite) {
+ ScopedRealUtf8Chars name(env, javaName);
+ if (name.c_str() == NULL) {
+ jniThrowNullPointerException(env);
+ }
+ ScopedRealUtf8Chars value(env, javaValue);
+ if (value.c_str() == NULL) {
+ jniThrowNullPointerException(env);
+ }
+ throwIfMinusOne(env, "setenv", setenv(name.c_str(), value.c_str(), overwrite ? 1 : 0));
+}
+
// ---- Registration ----
static const JNINativeMethod sMethods[] =
@@ -227,6 +240,7 @@
{ "lstat", "(Ljava/lang/String;)Landroid/system/StructStat;", (void*)Linux_lstat },
{ "stat", "(Ljava/lang/String;)Landroid/system/StructStat;", (void*)Linux_stat },
{ "nOpen", "(Ljava/lang/String;II)I", (void*)Linux_open },
+ { "setenv", "(Ljava/lang/String;Ljava/lang/String;Z)V", (void*)Linux_setenv },
};
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
diff --git a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
index 34239b8..9c86389 100644
--- a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
+++ b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
@@ -9,17 +9,13 @@
com.android.internal.logging.testing.UiEventLoggerFake
com.android.internal.os.AndroidPrintStream
com.android.internal.os.BatteryStatsHistory
-com.android.internal.os.BatteryStatsHistory$TraceDelegate
-com.android.internal.os.BatteryStatsHistory$VarintParceler
com.android.internal.os.BatteryStatsHistoryIterator
com.android.internal.os.Clock
com.android.internal.os.LongArrayMultiStateCounter
-com.android.internal.os.LongArrayMultiStateCounter$LongArrayContainer
com.android.internal.os.LongMultiStateCounter
com.android.internal.os.MonotonicClock
com.android.internal.os.PowerProfile
com.android.internal.os.PowerStats
-com.android.internal.os.PowerStats$Descriptor
com.android.internal.os.RuntimeInit
com.android.internal.power.EnergyConsumerStats
com.android.internal.power.ModemPowerProfile
@@ -123,15 +119,9 @@
android.os.BaseBundle
android.os.BatteryConsumer
android.os.BatteryStats
-android.os.BatteryStats$HistoryItem
-android.os.BatteryStats$HistoryStepDetails
-android.os.BatteryStats$HistoryTag
-android.os.BatteryStats$LongCounter
-android.os.BatteryStats$ProcessStateChange
android.os.BatteryUsageStats
android.os.BatteryUsageStatsQuery
android.os.Binder
-android.os.Binder$IdentitySupplier
android.os.BluetoothBatteryStats
android.os.Broadcaster
android.os.Build
@@ -142,7 +132,6 @@
android.os.DeadObjectException
android.os.DeadSystemException
android.os.FileUtils
-android.os.FileUtils$MemoryPipe
android.os.Handler
android.os.HandlerExecutor
android.os.HandlerThread
@@ -154,8 +143,6 @@
android.os.PackageTagsList
android.os.Parcel
android.os.ParcelFileDescriptor
-android.os.ParcelFileDescriptor$AutoCloseInputStream
-android.os.ParcelFileDescriptor$AutoCloseOutputStream
android.os.ParcelFormatException
android.os.ParcelUuid
android.os.Parcelable
@@ -169,7 +156,6 @@
android.os.RemoteException
android.os.ResultReceiver
android.os.ServiceManager
-android.os.ServiceManager$ServiceNotFoundException
android.os.ServiceSpecificException
android.os.StrictMode
android.os.SystemClock
@@ -180,18 +166,14 @@
android.os.Trace
android.os.TransactionTooLargeException
android.os.UserBatteryConsumer
-android.os.UserBatteryConsumer$Builder
android.os.UidBatteryConsumer
-android.os.UidBatteryConsumer$Builder
android.os.UserHandle
android.os.UserManager
android.os.VibrationAttributes
-android.os.VibrationAttributes$Builder
android.os.WakeLockStats
android.os.WorkSource
android.content.ClipData
-android.content.ClipData$Item
android.content.ClipDescription
android.content.ClipboardManager
android.content.ComponentName
@@ -208,11 +190,7 @@
android.content.pm.ComponentInfo
android.content.pm.PackageInfo
android.content.pm.PackageItemInfo
-android.content.pm.PackageManager$Flags
-android.content.pm.PackageManager$PackageInfoFlags
-android.content.pm.PackageManager$ApplicationInfoFlags
-android.content.pm.PackageManager$ComponentInfoFlags
-android.content.pm.PackageManager$ResolveInfoFlags
+android.content.pm.PackageManager
android.content.pm.PathPermission
android.content.pm.ProviderInfo
android.content.pm.ResolveInfo
@@ -223,7 +201,6 @@
android.content.res.ApkAssets
android.content.res.AssetFileDescriptor
android.content.res.AssetManager
-android.content.res.AssetManager$Builder
android.content.res.ColorStateList
android.content.res.ConfigurationBoundResourceCache
android.content.res.Configuration
@@ -237,7 +214,6 @@
android.content.res.FontScaleConverterImpl
android.content.res.FontScaleConverterFactory
android.content.res.Resources
-android.content.res.Resources$Theme
android.content.res.ResourceId
android.content.res.ResourcesImpl
android.content.res.ResourcesKey
@@ -260,7 +236,6 @@
android.database.DataSetObservable
android.database.DataSetObserver
android.database.MatrixCursor
-android.database.MatrixCursor$RowBuilder
android.database.MergeCursor
android.database.Observable
android.database.SQLException
@@ -268,7 +243,6 @@
android.database.sqlite.SQLiteException
android.text.TextUtils
-android.text.TextUtils$SimpleStringSplitter
android.accounts.Account
@@ -298,14 +272,11 @@
android.app.Instrumentation
android.app.LocaleConfig
android.app.ResourcesManager
-android.app.ResourcesManager$UpdateHandler
android.app.WindowConfiguration
android.metrics.LogMaker
android.view.Display
-android.view.Display$HdrCapabilities
-android.view.Display$Mode
android.view.DisplayAdjustments
android.view.DisplayInfo
android.view.inputmethod.InputBinding
diff --git a/ravenwood/texts/ravenwood-standard-options.txt b/ravenwood/texts/ravenwood-standard-options.txt
index f64f26d..3ec3e3c 100644
--- a/ravenwood/texts/ravenwood-standard-options.txt
+++ b/ravenwood/texts/ravenwood-standard-options.txt
@@ -6,8 +6,6 @@
--default-throw
# Uncomment below lines to enable each feature.
-# --enable-non-stub-method-check
---no-non-stub-method-check
#--default-method-call-hook
# com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
@@ -34,8 +32,11 @@
--substitute-annotation
android.ravenwood.annotation.RavenwoodReplace
---native-substitute-annotation
- android.ravenwood.annotation.RavenwoodNativeSubstitutionClass
+--redirect-annotation
+ android.ravenwood.annotation.RavenwoodRedirect
+
+--redirection-class-annotation
+ android.ravenwood.annotation.RavenwoodRedirectionClass
--class-load-hook-annotation
android.ravenwood.annotation.RavenwoodClassLoadHook
diff --git a/services/accessibility/accessibility.aconfig b/services/accessibility/accessibility.aconfig
index ffa4841..ee3bbca 100644
--- a/services/accessibility/accessibility.aconfig
+++ b/services/accessibility/accessibility.aconfig
@@ -216,6 +216,16 @@
}
flag {
+ name: "reset_input_dispatcher_before_first_touch_exploration"
+ namespace: "accessibility"
+ description: "Resets InputDispatcher state by sending ACTION_CANCEL before the first TouchExploration hover events"
+ bug: "364408887"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "scan_packages_without_lock"
namespace: "accessibility"
description: "Scans packages for accessibility service/activity info without holding the A11yMS lock"
@@ -228,6 +238,7 @@
description: "Sends accessibility events in TouchExplorer#onAccessibilityEvent based on internal state to keep it consistent. This reduces test flakiness."
bug: "295575684"
}
+
flag {
name: "send_hover_events_based_on_event_stream"
namespace: "accessibility"
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index d16a665..1b2447e 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -26,6 +26,7 @@
import android.annotation.NonNull;
import android.content.Context;
import android.graphics.Region;
+import android.hardware.input.InputManager;
import android.os.Looper;
import android.os.PowerManager;
import android.os.SystemClock;
@@ -57,6 +58,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Objects;
import java.util.StringJoiner;
/**
@@ -748,6 +750,7 @@
if ((mEnabledFeatures & FLAG_FEATURE_MOUSE_KEYS) != 0) {
mMouseKeysInterceptor = new MouseKeysInterceptor(mAms,
+ Objects.requireNonNull(mContext.getSystemService(InputManager.class)),
Looper.myLooper(),
Display.DEFAULT_DISPLAY);
addFirstEventHandler(Display.DEFAULT_DISPLAY, mMouseKeysInterceptor);
diff --git a/services/accessibility/java/com/android/server/accessibility/MouseKeysInterceptor.java b/services/accessibility/java/com/android/server/accessibility/MouseKeysInterceptor.java
index 2ce5c2b..54368ca 100644
--- a/services/accessibility/java/com/android/server/accessibility/MouseKeysInterceptor.java
+++ b/services/accessibility/java/com/android/server/accessibility/MouseKeysInterceptor.java
@@ -23,6 +23,7 @@
import android.annotation.RequiresPermission;
import android.companion.virtual.VirtualDeviceManager;
import android.companion.virtual.VirtualDeviceParams;
+import android.hardware.input.InputManager;
import android.hardware.input.VirtualMouse;
import android.hardware.input.VirtualMouseButtonEvent;
import android.hardware.input.VirtualMouseConfig;
@@ -34,8 +35,11 @@
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
+import android.view.InputDevice;
import android.view.KeyEvent;
+import androidx.annotation.VisibleForTesting;
+
import com.android.server.LocalServices;
import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
@@ -60,7 +64,7 @@
* mouse keys of each physical keyboard will control a single (global) mouse pointer.
*/
public class MouseKeysInterceptor extends BaseEventStreamTransformation
- implements Handler.Callback {
+ implements Handler.Callback, InputManager.InputDeviceListener {
private static final String LOG_TAG = "MouseKeysInterceptor";
// To enable these logs, run: 'adb shell setprop log.tag.MouseKeysInterceptor DEBUG'
@@ -77,10 +81,19 @@
private final AccessibilityManagerService mAms;
private final Handler mHandler;
+ private final InputManager mInputManager;
/** Thread to wait for virtual mouse creation to complete */
private final Thread mCreateVirtualMouseThread;
+ /**
+ * Map of device IDs to a map of key codes to their corresponding {@link MouseKeyEvent} values.
+ * To ensure thread safety for the map, all access and modification of the map
+ * should happen on the same thread, i.e., on the handler thread.
+ */
+ private final SparseArray<SparseArray<MouseKeyEvent>> mDeviceKeyCodeMap =
+ new SparseArray<>();
+
VirtualDeviceManager.VirtualDevice mVirtualDevice = null;
private VirtualMouse mVirtualMouse = null;
@@ -102,6 +115,21 @@
/** Whether scroll toggle is on */
private boolean mScrollToggleOn = false;
+ /** The ID of the input device that is currently active */
+ private int mActiveInputDeviceId = 0;
+
+ /**
+ * Enum representing different types of mouse key events, each associated with a specific
+ * key code.
+ *
+ * <p> These events correspond to various mouse actions such as directional movements,
+ * clicks, and scrolls, mapped to specific keys on the keyboard.
+ * The key codes here are the QWERTY key codes, and should be accessed via
+ * {@link MouseKeyEvent#getKeyCode(InputDevice)}
+ * so that it is mapped to the equivalent key on the keyboard layout of the keyboard device
+ * that is actually in use.
+ * </p>
+ */
public enum MouseKeyEvent {
DIAGONAL_UP_LEFT_MOVE(KeyEvent.KEYCODE_7),
UP_MOVE_OR_SCROLL(KeyEvent.KEYCODE_8),
@@ -117,34 +145,64 @@
RELEASE(KeyEvent.KEYCODE_COMMA),
SCROLL_TOGGLE(KeyEvent.KEYCODE_PERIOD);
- private final int mKeyCode;
+ private final int mLocationKeyCode;
MouseKeyEvent(int enumValue) {
- mKeyCode = enumValue;
+ mLocationKeyCode = enumValue;
}
- private static final SparseArray<MouseKeyEvent> VALUE_TO_ENUM_MAP = new SparseArray<>();
-
- static {
- for (MouseKeyEvent type : MouseKeyEvent.values()) {
- VALUE_TO_ENUM_MAP.put(type.mKeyCode, type);
- }
- }
-
+ @VisibleForTesting
public final int getKeyCodeValue() {
- return mKeyCode;
+ return mLocationKeyCode;
}
/**
- * Convert int value of the key code to corresponding MouseEvent enum. If no matching
- * value is found, this will return {@code null}.
+ * Get the key code associated with the given MouseKeyEvent for the given keyboard
+ * input device, taking into account its layout.
+ * The default is to return the keycode for the default layout (QWERTY).
+ * We check if the input device has been generated using {@link InputDevice#getGeneration()}
+ * to test with the default {@link MouseKeyEvent} values in the unit tests.
+ */
+ public int getKeyCode(InputDevice inputDevice) {
+ if (inputDevice.getGeneration() == -1) {
+ return mLocationKeyCode;
+ }
+ return inputDevice.getKeyCodeForKeyLocation(mLocationKeyCode);
+ }
+
+ /**
+ * Convert int value of the key code to corresponding {@link MouseKeyEvent}
+ * enum for a particular device ID.
+ * If no matching value is found, this will return {@code null}.
*/
@Nullable
- public static MouseKeyEvent from(int value) {
- return VALUE_TO_ENUM_MAP.get(value);
+ public static MouseKeyEvent from(int keyCode, int deviceId,
+ SparseArray<SparseArray<MouseKeyEvent>> deviceKeyCodeMap) {
+ SparseArray<MouseKeyEvent> keyCodeToEnumMap = deviceKeyCodeMap.get(deviceId);
+ if (keyCodeToEnumMap != null) {
+ return keyCodeToEnumMap.get(keyCode);
+ }
+ return null;
}
}
/**
+ * Create a map of key codes to their corresponding {@link MouseKeyEvent} values
+ * for a specific input device.
+ * The key for {@code mDeviceKeyCodeMap} is the deviceId.
+ * The key for {@code keyCodeToEnumMap} is the keycode for each
+ * {@link MouseKeyEvent} according to the keyboard layout of the input device.
+ */
+ public void initializeDeviceToEnumMap(InputDevice inputDevice) {
+ int deviceId = inputDevice.getId();
+ SparseArray<MouseKeyEvent> keyCodeToEnumMap = new SparseArray<>();
+ for (MouseKeyEvent mouseKeyEventType : MouseKeyEvent.values()) {
+ int keyCode = mouseKeyEventType.getKeyCode(inputDevice);
+ keyCodeToEnumMap.put(keyCode, mouseKeyEventType);
+ }
+ mDeviceKeyCodeMap.put(deviceId, keyCodeToEnumMap);
+ }
+
+ /**
* Construct a new MouseKeysInterceptor.
*
* @param service The service to notify of key events
@@ -152,8 +210,10 @@
* @param displayId Display ID to send mouse events to
*/
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
- public MouseKeysInterceptor(AccessibilityManagerService service, Looper looper, int displayId) {
+ public MouseKeysInterceptor(AccessibilityManagerService service,
+ InputManager inputManager, Looper looper, int displayId) {
mAms = service;
+ mInputManager = inputManager;
mHandler = new Handler(looper, this);
// Create the virtual mouse on a separate thread since virtual device creation
// should happen on an auxiliary thread, and not from the handler's thread.
@@ -163,6 +223,9 @@
mVirtualMouse = createVirtualMouse(displayId);
});
mCreateVirtualMouseThread.start();
+ // Register an input device listener to watch when input devices are
+ // added, removed or reconfigured.
+ mInputManager.registerInputDeviceListener(this, mHandler);
}
/**
@@ -215,7 +278,8 @@
*/
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
private void performMouseScrollAction(int keyCode) {
- MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from(keyCode);
+ MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from(
+ keyCode, mActiveInputDeviceId, mDeviceKeyCodeMap);
float y = switch (mouseKeyEvent) {
case UP_MOVE_OR_SCROLL -> 1.0f;
case DOWN_MOVE_OR_SCROLL -> -1.0f;
@@ -247,15 +311,18 @@
*/
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
private void performMouseButtonAction(int keyCode) {
- MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from(keyCode);
+ MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from(
+ keyCode, mActiveInputDeviceId, mDeviceKeyCodeMap);
int buttonCode = switch (mouseKeyEvent) {
case LEFT_CLICK -> VirtualMouseButtonEvent.BUTTON_PRIMARY;
case RIGHT_CLICK -> VirtualMouseButtonEvent.BUTTON_SECONDARY;
default -> VirtualMouseButtonEvent.BUTTON_UNKNOWN;
};
if (buttonCode != VirtualMouseButtonEvent.BUTTON_UNKNOWN) {
- sendVirtualMouseButtonEvent(buttonCode, VirtualMouseButtonEvent.ACTION_BUTTON_PRESS);
- sendVirtualMouseButtonEvent(buttonCode, VirtualMouseButtonEvent.ACTION_BUTTON_RELEASE);
+ sendVirtualMouseButtonEvent(buttonCode,
+ VirtualMouseButtonEvent.ACTION_BUTTON_PRESS);
+ sendVirtualMouseButtonEvent(buttonCode,
+ VirtualMouseButtonEvent.ACTION_BUTTON_RELEASE);
}
if (DEBUG) {
if (buttonCode == VirtualMouseButtonEvent.BUTTON_UNKNOWN) {
@@ -293,7 +360,9 @@
private void performMousePointerAction(int keyCode) {
float x = 0f;
float y = 0f;
- MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from(keyCode);
+ MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from(
+ keyCode, mActiveInputDeviceId, mDeviceKeyCodeMap);
+
switch (mouseKeyEvent) {
case DIAGONAL_DOWN_LEFT_MOVE -> {
x = -MOUSE_POINTER_MOVEMENT_STEP / sqrt(2);
@@ -339,18 +408,19 @@
}
}
- private boolean isMouseKey(int keyCode) {
- return MouseKeyEvent.VALUE_TO_ENUM_MAP.contains(keyCode);
+ private boolean isMouseKey(int keyCode, int deviceId) {
+ SparseArray<MouseKeyEvent> keyCodeToEnumMap = mDeviceKeyCodeMap.get(deviceId);
+ return keyCodeToEnumMap.contains(keyCode);
}
- private boolean isMouseButtonKey(int keyCode) {
- return keyCode == MouseKeyEvent.LEFT_CLICK.getKeyCodeValue()
- || keyCode == MouseKeyEvent.RIGHT_CLICK.getKeyCodeValue();
+ private boolean isMouseButtonKey(int keyCode, InputDevice inputDevice) {
+ return keyCode == MouseKeyEvent.LEFT_CLICK.getKeyCode(inputDevice)
+ || keyCode == MouseKeyEvent.RIGHT_CLICK.getKeyCode(inputDevice);
}
- private boolean isMouseScrollKey(int keyCode) {
- return keyCode == MouseKeyEvent.UP_MOVE_OR_SCROLL.getKeyCodeValue()
- || keyCode == MouseKeyEvent.DOWN_MOVE_OR_SCROLL.getKeyCodeValue();
+ private boolean isMouseScrollKey(int keyCode, InputDevice inputDevice) {
+ return keyCode == MouseKeyEvent.UP_MOVE_OR_SCROLL.getKeyCode(inputDevice)
+ || keyCode == MouseKeyEvent.DOWN_MOVE_OR_SCROLL.getKeyCode(inputDevice);
}
/**
@@ -373,7 +443,7 @@
}
/**
- * Handles key events and forwards mouse key events to the virtual mouse.
+ * Handles key events and forwards mouse key events to the virtual mouse on the handler thread.
*
* @param event The key event to handle.
* @param policyFlags The policy flags associated with the key event.
@@ -385,31 +455,45 @@
mAms.getTraceManager().logTrace(LOG_TAG + ".onKeyEvent",
FLAGS_INPUT_FILTER, "event=" + event + ";policyFlags=" + policyFlags);
}
+
+ mHandler.post(() -> {
+ onKeyEventInternal(event, policyFlags);
+ });
+ }
+
+ @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
+ private void onKeyEventInternal(KeyEvent event, int policyFlags) {
boolean isDown = event.getAction() == KeyEvent.ACTION_DOWN;
int keyCode = event.getKeyCode();
+ mActiveInputDeviceId = event.getDeviceId();
+ InputDevice inputDevice = mInputManager.getInputDevice(mActiveInputDeviceId);
- if (!isMouseKey(keyCode)) {
+ if (!mDeviceKeyCodeMap.contains(mActiveInputDeviceId)) {
+ initializeDeviceToEnumMap(inputDevice);
+ }
+
+ if (!isMouseKey(keyCode, mActiveInputDeviceId)) {
// Pass non-mouse key events to the next handler
super.onKeyEvent(event, policyFlags);
} else if (isDown) {
- if (keyCode == MouseKeyEvent.SCROLL_TOGGLE.getKeyCodeValue()) {
+ if (keyCode == MouseKeyEvent.SCROLL_TOGGLE.getKeyCode(inputDevice)) {
mScrollToggleOn = !mScrollToggleOn;
if (DEBUG) {
Slog.d(LOG_TAG, "Scroll toggle " + (mScrollToggleOn ? "ON" : "OFF"));
}
- } else if (keyCode == MouseKeyEvent.HOLD.getKeyCodeValue()) {
+ } else if (keyCode == MouseKeyEvent.HOLD.getKeyCode(inputDevice)) {
sendVirtualMouseButtonEvent(
VirtualMouseButtonEvent.BUTTON_PRIMARY,
VirtualMouseButtonEvent.ACTION_BUTTON_PRESS
);
- } else if (keyCode == MouseKeyEvent.RELEASE.getKeyCodeValue()) {
+ } else if (keyCode == MouseKeyEvent.RELEASE.getKeyCode(inputDevice)) {
sendVirtualMouseButtonEvent(
VirtualMouseButtonEvent.BUTTON_PRIMARY,
VirtualMouseButtonEvent.ACTION_BUTTON_RELEASE
);
- } else if (isMouseButtonKey(keyCode)) {
+ } else if (isMouseButtonKey(keyCode, inputDevice)) {
performMouseButtonAction(keyCode);
- } else if (mScrollToggleOn && isMouseScrollKey(keyCode)) {
+ } else if (mScrollToggleOn && isMouseScrollKey(keyCode, inputDevice)) {
// If the scroll key is pressed down and no other key is active,
// set it as the active key and send a message to scroll the pointer
if (mActiveScrollKey == KEY_NOT_SET) {
@@ -439,7 +523,8 @@
mHandler.removeMessages(MESSAGE_SCROLL_MOUSE_POINTER);
} else {
Slog.i(LOG_TAG, "Dropping event with key code: '" + keyCode
- + "', with no matching down event from deviceId = " + event.getDeviceId());
+ + "', with no matching down event from deviceId = "
+ + event.getDeviceId());
}
}
}
@@ -503,12 +588,40 @@
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@Override
public void onDestroy() {
- // Clear mouse state
- mActiveMoveKey = KEY_NOT_SET;
- mActiveScrollKey = KEY_NOT_SET;
- mLastTimeKeyActionPerformed = 0;
+ mHandler.post(() -> {
+ // Clear mouse state
+ mActiveMoveKey = KEY_NOT_SET;
+ mActiveScrollKey = KEY_NOT_SET;
+ mLastTimeKeyActionPerformed = 0;
+ mDeviceKeyCodeMap.clear();
+ });
mHandler.removeCallbacksAndMessages(null);
mVirtualDevice.close();
}
+
+ @Override
+ public void onInputDeviceAdded(int deviceId) {
+ }
+
+ @Override
+ public void onInputDeviceRemoved(int deviceId) {
+ mDeviceKeyCodeMap.remove(deviceId);
+ }
+
+ /**
+ * The user can change the keyboard layout from settings at anytime, which would change
+ * key character map for that device. Hence, we should use this callback to
+ * update the key code to enum mapping if there is a change in the physical keyboard detected.
+ *
+ * @param deviceId The id of the input device that changed.
+ */
+ @Override
+ public void onInputDeviceChanged(int deviceId) {
+ InputDevice inputDevice = mInputManager.getInputDevice(deviceId);
+ // Update the enum mapping only if input device that changed is a keyboard
+ if (inputDevice.isFullKeyboard() && !mDeviceKeyCodeMap.contains(deviceId)) {
+ initializeDeviceToEnumMap(inputDevice);
+ }
+ }
}
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index 04b42e4..0ed239e 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -1613,6 +1613,19 @@
dispatchGesture(gestureEvent);
}
if (!mEvents.isEmpty() && !mRawEvents.isEmpty()) {
+ if (Flags.resetInputDispatcherBeforeFirstTouchExploration()
+ && !mState.hasResetInputDispatcherState()) {
+ // Cancel any possible ongoing touch gesture from before touch exploration
+ // started. This clears out the InputDispatcher event stream state so that it
+ // is ready to accept new injected HOVER events.
+ mDispatcher.sendMotionEvent(
+ mEvents.get(0),
+ ACTION_CANCEL,
+ mRawEvents.get(0),
+ mPointerIdBits,
+ mPolicyFlags);
+ setHasResetInputDispatcherState(true);
+ }
// Deliver a down event.
mDispatcher.sendMotionEvent(
mEvents.get(0),
@@ -1773,4 +1786,9 @@
+ ", mDraggingPointerId: " + mDraggingPointerId
+ " }";
}
+
+ @VisibleForTesting
+ void setHasResetInputDispatcherState(boolean value) {
+ mState.setHasResetInputDispatcherState(value);
+ }
}
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java
index e13994e..f15b8ee 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java
@@ -86,6 +86,7 @@
private MotionEvent mLastInjectedHoverEvent;
// The last injected hover event used for performing clicks.
private MotionEvent mLastInjectedHoverEventForClick;
+ private boolean mHasResetInputDispatcherState;
// The time of the last injected down.
private long mLastInjectedDownEventTime;
// Keep track of which pointers sent to the system are down.
@@ -361,6 +362,14 @@
return mLastInjectedDownEventTime;
}
+ boolean hasResetInputDispatcherState() {
+ return mHasResetInputDispatcherState;
+ }
+
+ void setHasResetInputDispatcherState(boolean value) {
+ mHasResetInputDispatcherState = value;
+ }
+
public int getLastTouchedWindowId() {
return mLastTouchedWindowId;
}
diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerService.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerService.java
index a2d467c..02800cb 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerService.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerService.java
@@ -21,9 +21,7 @@
import com.android.server.SystemService;
-/**
- * Service that manages app functions.
- */
+/** Service that manages app functions. */
public class AppFunctionManagerService extends SystemService {
private final AppFunctionManagerServiceImpl mServiceImpl;
diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
index 32b8d6b..f04bd9f 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
@@ -39,9 +39,7 @@
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
-/**
- * Implementation of the AppFunctionManagerService.
- */
+/** Implementation of the AppFunctionManagerService. */
public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub {
private static final String TAG = AppFunctionManagerServiceImpl.class.getSimpleName();
@@ -50,30 +48,31 @@
private final ServiceHelper mInternalServiceHelper;
private final ServiceConfig mServiceConfig;
-
public AppFunctionManagerServiceImpl(@NonNull Context context) {
- this(new RemoteServiceCallerImpl<>(
+ this(
+ new RemoteServiceCallerImpl<>(
context,
- IAppFunctionService.Stub::asInterface, new ThreadPoolExecutor(
- /*corePoolSize=*/ Runtime.getRuntime().availableProcessors(),
- /*maxConcurrency=*/ Runtime.getRuntime().availableProcessors(),
- /*keepAliveTime=*/ 0L,
- /*unit=*/ TimeUnit.SECONDS,
- /*workQueue=*/ new LinkedBlockingQueue<>())),
+ IAppFunctionService.Stub::asInterface,
+ new ThreadPoolExecutor(
+ /* corePoolSize= */ Runtime.getRuntime().availableProcessors(),
+ /* maxConcurrency= */ Runtime.getRuntime().availableProcessors(),
+ /* keepAliveTime= */ 0L,
+ /* unit= */ TimeUnit.SECONDS,
+ /* workQueue= */ new LinkedBlockingQueue<>())),
new CallerValidatorImpl(context),
new ServiceHelperImpl(context),
new ServiceConfigImpl());
}
@VisibleForTesting
- AppFunctionManagerServiceImpl(RemoteServiceCaller<IAppFunctionService> remoteServiceCaller,
- CallerValidator callerValidator,
- ServiceHelper appFunctionInternalServiceHelper,
- ServiceConfig serviceConfig) {
+ AppFunctionManagerServiceImpl(
+ RemoteServiceCaller<IAppFunctionService> remoteServiceCaller,
+ CallerValidator callerValidator,
+ ServiceHelper appFunctionInternalServiceHelper,
+ ServiceConfig serviceConfig) {
mRemoteServiceCaller = Objects.requireNonNull(remoteServiceCaller);
mCallerValidator = Objects.requireNonNull(callerValidator);
- mInternalServiceHelper =
- Objects.requireNonNull(appFunctionInternalServiceHelper);
+ mInternalServiceHelper = Objects.requireNonNull(appFunctionInternalServiceHelper);
mServiceConfig = serviceConfig;
}
@@ -90,65 +89,71 @@
String validatedCallingPackage;
UserHandle targetUser;
try {
- validatedCallingPackage = mCallerValidator
- .validateCallingPackage(requestInternal.getCallingPackage());
- targetUser = mCallerValidator.verifyTargetUserHandle(
- requestInternal.getUserHandle(), validatedCallingPackage);
+ validatedCallingPackage =
+ mCallerValidator.validateCallingPackage(requestInternal.getCallingPackage());
+ targetUser =
+ mCallerValidator.verifyTargetUserHandle(
+ requestInternal.getUserHandle(), validatedCallingPackage);
} catch (SecurityException exception) {
- safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse
- .newFailure(ExecuteAppFunctionResponse.RESULT_DENIED,
+ safeExecuteAppFunctionCallback.onResult(
+ ExecuteAppFunctionResponse.newFailure(
+ ExecuteAppFunctionResponse.RESULT_DENIED,
exception.getMessage(),
- /*extras=*/ null));
+ /* extras= */ null));
return;
}
// TODO(b/354956319): Add and honor the new enterprise policies.
if (mCallerValidator.isUserOrganizationManaged(targetUser)) {
- safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse.newFailure(
- ExecuteAppFunctionResponse.RESULT_INTERNAL_ERROR,
- "Cannot run on a device with a device owner or from the managed profile.",
- /*extras=*/ null
- ));
+ safeExecuteAppFunctionCallback.onResult(
+ ExecuteAppFunctionResponse.newFailure(
+ ExecuteAppFunctionResponse.RESULT_INTERNAL_ERROR,
+ "Cannot run on a device with a device owner or from the managed"
+ + " profile.",
+ /* extras= */ null));
return;
}
String targetPackageName = requestInternal.getClientRequest().getTargetPackageName();
if (TextUtils.isEmpty(targetPackageName)) {
- safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse.newFailure(
- ExecuteAppFunctionResponse.RESULT_INVALID_ARGUMENT,
- "Target package name cannot be empty.",
- /*extras=*/ null
- ));
+ safeExecuteAppFunctionCallback.onResult(
+ ExecuteAppFunctionResponse.newFailure(
+ ExecuteAppFunctionResponse.RESULT_INVALID_ARGUMENT,
+ "Target package name cannot be empty.",
+ /* extras= */ null));
return;
}
if (!mCallerValidator.verifyCallerCanExecuteAppFunction(
validatedCallingPackage, targetPackageName)) {
- safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse
- .newFailure(ExecuteAppFunctionResponse.RESULT_DENIED,
+ safeExecuteAppFunctionCallback.onResult(
+ ExecuteAppFunctionResponse.newFailure(
+ ExecuteAppFunctionResponse.RESULT_DENIED,
"Caller does not have permission to execute the appfunction",
- /*extras=*/ null));
+ /* extras= */ null));
return;
}
- Intent serviceIntent = mInternalServiceHelper.resolveAppFunctionService(
- targetPackageName,
- targetUser);
+ Intent serviceIntent =
+ mInternalServiceHelper.resolveAppFunctionService(targetPackageName, targetUser);
if (serviceIntent == null) {
- safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse.newFailure(
- ExecuteAppFunctionResponse.RESULT_INTERNAL_ERROR,
- "Cannot find the target service.",
- /*extras=*/ null
- ));
+ safeExecuteAppFunctionCallback.onResult(
+ ExecuteAppFunctionResponse.newFailure(
+ ExecuteAppFunctionResponse.RESULT_INTERNAL_ERROR,
+ "Cannot find the target service.",
+ /* extras= */ null));
return;
}
final long token = Binder.clearCallingIdentity();
try {
- bindAppFunctionServiceUnchecked(requestInternal, serviceIntent, targetUser,
- safeExecuteAppFunctionCallback,
- /*bindFlags=*/ Context.BIND_AUTO_CREATE,
- /*timeoutInMillis=*/ mServiceConfig.getExecuteAppFunctionTimeoutMillis());
+ bindAppFunctionServiceUnchecked(
+ requestInternal,
+ serviceIntent,
+ targetUser,
+ safeExecuteAppFunctionCallback,
+ /* bindFlags= */ Context.BIND_AUTO_CREATE,
+ /* timeoutInMillis= */ mServiceConfig.getExecuteAppFunctionTimeoutMillis());
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -156,69 +161,75 @@
private void bindAppFunctionServiceUnchecked(
@NonNull ExecuteAppFunctionAidlRequest requestInternal,
- @NonNull Intent serviceIntent, @NonNull UserHandle targetUser,
- @NonNull SafeOneTimeExecuteAppFunctionCallback
- safeExecuteAppFunctionCallback,
- int bindFlags, long timeoutInMillis) {
- boolean bindServiceResult = mRemoteServiceCaller.runServiceCall(
- serviceIntent,
- bindFlags,
- timeoutInMillis,
- targetUser,
- new RunServiceCallCallback<IAppFunctionService>() {
- @Override
- public void onServiceConnected(@NonNull IAppFunctionService service,
- @NonNull ServiceUsageCompleteListener
- serviceUsageCompleteListener) {
- try {
- service.executeAppFunction(
- requestInternal.getClientRequest(),
- new IExecuteAppFunctionCallback.Stub() {
- @Override
- public void onResult(ExecuteAppFunctionResponse response) {
- safeExecuteAppFunctionCallback.onResult(response);
- serviceUsageCompleteListener.onCompleted();
- }
- }
- );
- } catch (Exception e) {
- safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse
- .newFailure(ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR,
- e.getMessage(),
- /*extras=*/ null));
- serviceUsageCompleteListener.onCompleted();
- }
- }
+ @NonNull Intent serviceIntent,
+ @NonNull UserHandle targetUser,
+ @NonNull SafeOneTimeExecuteAppFunctionCallback safeExecuteAppFunctionCallback,
+ int bindFlags,
+ long timeoutInMillis) {
+ boolean bindServiceResult =
+ mRemoteServiceCaller.runServiceCall(
+ serviceIntent,
+ bindFlags,
+ timeoutInMillis,
+ targetUser,
+ new RunServiceCallCallback<IAppFunctionService>() {
+ @Override
+ public void onServiceConnected(
+ @NonNull IAppFunctionService service,
+ @NonNull
+ ServiceUsageCompleteListener
+ serviceUsageCompleteListener) {
+ try {
+ service.executeAppFunction(
+ requestInternal.getClientRequest(),
+ new IExecuteAppFunctionCallback.Stub() {
+ @Override
+ public void onResult(
+ ExecuteAppFunctionResponse response) {
+ safeExecuteAppFunctionCallback.onResult(
+ response);
+ serviceUsageCompleteListener.onCompleted();
+ }
+ });
+ } catch (Exception e) {
+ safeExecuteAppFunctionCallback.onResult(
+ ExecuteAppFunctionResponse.newFailure(
+ ExecuteAppFunctionResponse
+ .RESULT_APP_UNKNOWN_ERROR,
+ e.getMessage(),
+ /* extras= */ null));
+ serviceUsageCompleteListener.onCompleted();
+ }
+ }
- @Override
- public void onFailedToConnect() {
- Slog.e(TAG, "Failed to connect to service");
- safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse
- .newFailure(ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR,
- "Failed to connect to AppFunctionService",
- /*extras=*/ null));
- }
+ @Override
+ public void onFailedToConnect() {
+ Slog.e(TAG, "Failed to connect to service");
+ safeExecuteAppFunctionCallback.onResult(
+ ExecuteAppFunctionResponse.newFailure(
+ ExecuteAppFunctionResponse.RESULT_APP_UNKNOWN_ERROR,
+ "Failed to connect to AppFunctionService",
+ /* extras= */ null));
+ }
- @Override
- public void onTimedOut() {
- Slog.e(TAG, "Timed out");
- safeExecuteAppFunctionCallback.onResult(
- ExecuteAppFunctionResponse.newFailure(
- ExecuteAppFunctionResponse.RESULT_TIMED_OUT,
- "Binding to AppFunctionService timed out.",
- /*extras=*/ null
- ));
- }
- }
- );
+ @Override
+ public void onTimedOut() {
+ Slog.e(TAG, "Timed out");
+ safeExecuteAppFunctionCallback.onResult(
+ ExecuteAppFunctionResponse.newFailure(
+ ExecuteAppFunctionResponse.RESULT_TIMED_OUT,
+ "Binding to AppFunctionService timed out.",
+ /* extras= */ null));
+ }
+ });
if (!bindServiceResult) {
Slog.e(TAG, "Failed to bind to the AppFunctionService");
- safeExecuteAppFunctionCallback.onResult(ExecuteAppFunctionResponse.newFailure(
- ExecuteAppFunctionResponse.RESULT_TIMED_OUT,
- "Failed to bind the AppFunctionService.",
- /*extras=*/ null
- ));
+ safeExecuteAppFunctionCallback.onResult(
+ ExecuteAppFunctionResponse.newFailure(
+ ExecuteAppFunctionResponse.RESULT_TIMED_OUT,
+ "Failed to bind the AppFunctionService.",
+ /* extras= */ null));
}
}
}
diff --git a/services/appfunctions/java/com/android/server/appfunctions/CallerValidator.java b/services/appfunctions/java/com/android/server/appfunctions/CallerValidator.java
index 9bd633f..ca43dfa 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/CallerValidator.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/CallerValidator.java
@@ -22,7 +22,6 @@
import com.android.internal.annotations.VisibleForTesting;
-
/**
* Interface for validating that the caller has the correct privilege to call an AppFunctionManager
* API.
@@ -33,8 +32,8 @@
// TODO(b/357551503): Verify that user have been unlocked.
/**
- * This method is used to validate that the calling package reported in the request is the
- * same as the binder calling identity.
+ * This method is used to validate that the calling package reported in the request is the same
+ * as the binder calling identity.
*
* @param claimedCallingPackage The package name of the caller.
* @return The package name of the caller.
@@ -43,29 +42,29 @@
String validateCallingPackage(@NonNull String claimedCallingPackage);
/**
- * Validates that the caller can invoke an AppFunctionManager API in the provided
- * target user space.
+ * Validates that the caller can invoke an AppFunctionManager API in the provided target user
+ * space.
*
- * @param targetUserHandle The user which the caller is requesting to execute as.
+ * @param targetUserHandle The user which the caller is requesting to execute as.
* @param claimedCallingPackage The package name of the caller.
* @return The user handle that the call should run as. Will always be a concrete user.
* @throws IllegalArgumentException if the target user is a special user.
- * @throws SecurityException if caller trying to interact across users without {@link
- * Manifest.permission#INTERACT_ACROSS_USERS_FULL}
+ * @throws SecurityException if caller trying to interact across users without {@link
+ * Manifest.permission#INTERACT_ACROSS_USERS_FULL}
*/
- UserHandle verifyTargetUserHandle(@NonNull UserHandle targetUserHandle,
- @NonNull String claimedCallingPackage);
+ UserHandle verifyTargetUserHandle(
+ @NonNull UserHandle targetUserHandle, @NonNull String claimedCallingPackage);
/**
* Validates that the caller can execute the specified app function.
- * <p>
- * The caller can execute if the app function's package name is the same as the caller's package
- * or the caller has either {@link Manifest.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or
- * {@link Manifest.permission.EXECUTE_APP_FUNCTIONS} granted. In some cases, app functions
- * can still opt-out of caller having {@link Manifest.permission.EXECUTE_APP_FUNCTIONS}.
*
- * @param callerPackageName The calling package (as previously validated).
- * @param targetPackageName The package that owns the app function to execute.
+ * <p>The caller can execute if the app function's package name is the same as the caller's
+ * package or the caller has either {@link Manifest.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or
+ * {@link Manifest.permission.EXECUTE_APP_FUNCTIONS} granted. In some cases, app functions can
+ * still opt-out of caller having {@link Manifest.permission.EXECUTE_APP_FUNCTIONS}.
+ *
+ * @param callerPackageName The calling package (as previously validated).
+ * @param targetPackageName The package that owns the app function to execute.
* @return Whether the caller can execute the specified app function.
*/
boolean verifyCallerCanExecuteAppFunction(
diff --git a/services/appfunctions/java/com/android/server/appfunctions/CallerValidatorImpl.java b/services/appfunctions/java/com/android/server/appfunctions/CallerValidatorImpl.java
index 7cd660d..35905ed 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/CallerValidatorImpl.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/CallerValidatorImpl.java
@@ -34,7 +34,6 @@
class CallerValidatorImpl implements CallerValidator {
private final Context mContext;
-
CallerValidatorImpl(@NonNull Context context) {
mContext = Objects.requireNonNull(context);
}
@@ -56,14 +55,14 @@
@Override
@NonNull
@BinderThread
- public UserHandle verifyTargetUserHandle(@NonNull UserHandle targetUserHandle,
- @NonNull String claimedCallingPackage) {
+ public UserHandle verifyTargetUserHandle(
+ @NonNull UserHandle targetUserHandle, @NonNull String claimedCallingPackage) {
int callingPid = Binder.getCallingPid();
int callingUid = Binder.getCallingUid();
final long callingIdentityToken = Binder.clearCallingIdentity();
try {
- return handleIncomingUser(claimedCallingPackage, targetUserHandle,
- callingPid, callingUid);
+ return handleIncomingUser(
+ claimedCallingPackage, targetUserHandle, callingPid, callingUid);
} finally {
Binder.restoreCallingIdentity(callingIdentityToken);
}
@@ -71,19 +70,24 @@
@Override
@BinderThread
- @RequiresPermission(anyOf = {Manifest.permission.EXECUTE_APP_FUNCTIONS_TRUSTED,
- Manifest.permission.EXECUTE_APP_FUNCTIONS}, conditional = true)
+ @RequiresPermission(
+ anyOf = {
+ Manifest.permission.EXECUTE_APP_FUNCTIONS_TRUSTED,
+ Manifest.permission.EXECUTE_APP_FUNCTIONS
+ },
+ conditional = true)
// TODO(b/360864791): Add and honor apps that opt-out from EXECUTE_APP_FUNCTIONS caller.
public boolean verifyCallerCanExecuteAppFunction(
@NonNull String callerPackageName, @NonNull String targetPackageName) {
int pid = Binder.getCallingPid();
int uid = Binder.getCallingUid();
- boolean hasExecutionPermission = mContext.checkPermission(
- Manifest.permission.EXECUTE_APP_FUNCTIONS_TRUSTED, pid, uid)
- == PackageManager.PERMISSION_GRANTED;
- boolean hasTrustedExecutionPermission = mContext.checkPermission(
- Manifest.permission.EXECUTE_APP_FUNCTIONS, pid, uid)
- == PackageManager.PERMISSION_GRANTED;
+ boolean hasExecutionPermission =
+ mContext.checkPermission(
+ Manifest.permission.EXECUTE_APP_FUNCTIONS_TRUSTED, pid, uid)
+ == PackageManager.PERMISSION_GRANTED;
+ boolean hasTrustedExecutionPermission =
+ mContext.checkPermission(Manifest.permission.EXECUTE_APP_FUNCTIONS, pid, uid)
+ == PackageManager.PERMISSION_GRANTED;
boolean isSamePackage = callerPackageName.equals(targetPackageName);
return hasExecutionPermission || hasTrustedExecutionPermission || isSamePackage;
}
@@ -111,13 +115,13 @@
* simply throw.
*
* @param callingPackageName The package name of the caller.
- * @param targetUserHandle The user which the caller is requesting to execute as.
- * @param callingPid The actual pid of the caller as determined by Binder.
- * @param callingUid The actual uid of the caller as determined by Binder.
+ * @param targetUserHandle The user which the caller is requesting to execute as.
+ * @param callingPid The actual pid of the caller as determined by Binder.
+ * @param callingUid The actual uid of the caller as determined by Binder.
* @return the user handle that the call should run as. Will always be a concrete user.
* @throws IllegalArgumentException if the target user is a special user.
- * @throws SecurityException if caller trying to interact across user without {@link
- * Manifest.permission#INTERACT_ACROSS_USERS_FULL}
+ * @throws SecurityException if caller trying to interact across user without {@link
+ * Manifest.permission#INTERACT_ACROSS_USERS_FULL}
*/
@NonNull
private UserHandle handleIncomingUser(
@@ -137,7 +141,7 @@
}
if (mContext.checkPermission(
- Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingPid, callingUid)
+ Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingPid, callingUid)
== PackageManager.PERMISSION_GRANTED) {
try {
mContext.createPackageContextAsUser(
@@ -168,10 +172,9 @@
private void validateCallingPackageInternal(
int actualCallingUid, @NonNull String claimedCallingPackage) {
UserHandle callingUserHandle = UserHandle.getUserHandleForUid(actualCallingUid);
- Context actualCallingUserContext = mContext.createContextAsUser(
- callingUserHandle, /* flags= */ 0);
- int claimedCallingUid =
- getPackageUid(actualCallingUserContext, claimedCallingPackage);
+ Context actualCallingUserContext =
+ mContext.createContextAsUser(callingUserHandle, /* flags= */ 0);
+ int claimedCallingUid = getPackageUid(actualCallingUserContext, claimedCallingPackage);
if (claimedCallingUid != actualCallingUid) {
throw new SecurityException(
"Specified calling package ["
diff --git a/services/appfunctions/java/com/android/server/appfunctions/FutureAppSearchSession.java b/services/appfunctions/java/com/android/server/appfunctions/FutureAppSearchSession.java
new file mode 100644
index 0000000..0947238
--- /dev/null
+++ b/services/appfunctions/java/com/android/server/appfunctions/FutureAppSearchSession.java
@@ -0,0 +1,249 @@
+/*
+ * 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.appfunctions;
+
+import android.annotation.NonNull;
+import android.app.appsearch.AppSearchBatchResult;
+import android.app.appsearch.AppSearchManager;
+import android.app.appsearch.AppSearchManager.SearchContext;
+import android.app.appsearch.AppSearchResult;
+import android.app.appsearch.AppSearchSession;
+import android.app.appsearch.BatchResultCallback;
+import android.app.appsearch.GenericDocument;
+import android.app.appsearch.GetByDocumentIdRequest;
+import android.app.appsearch.GetSchemaResponse;
+import android.app.appsearch.PutDocumentsRequest;
+import android.app.appsearch.SearchResult;
+import android.app.appsearch.SearchResults;
+import android.app.appsearch.SearchSpec;
+import android.app.appsearch.SetSchemaRequest;
+import android.app.appsearch.SetSchemaResponse;
+import android.util.Slog;
+
+import com.android.internal.infra.AndroidFuture;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.Executor;
+
+/** A future API wrapper of {@link AppSearchSession} APIs. */
+public class FutureAppSearchSession implements Closeable {
+ private static final String TAG = FutureAppSearchSession.class.getSimpleName();
+ private final Executor mExecutor;
+ private final AndroidFuture<AppSearchResult<AppSearchSession>> mSettableSessionFuture;
+
+ public FutureAppSearchSession(
+ @NonNull AppSearchManager appSearchManager,
+ @NonNull Executor executor,
+ @NonNull SearchContext appSearchContext) {
+ Objects.requireNonNull(appSearchManager);
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(appSearchContext);
+
+ mExecutor = executor;
+ mSettableSessionFuture = new AndroidFuture<>();
+ appSearchManager.createSearchSession(
+ appSearchContext, mExecutor, mSettableSessionFuture::complete);
+ }
+
+ /** Converts a failed app search result codes into an exception. */
+ @NonNull
+ public static Exception failedResultToException(@NonNull AppSearchResult<?> appSearchResult) {
+ return switch (appSearchResult.getResultCode()) {
+ case AppSearchResult.RESULT_INVALID_ARGUMENT ->
+ new IllegalArgumentException(appSearchResult.getErrorMessage());
+ case AppSearchResult.RESULT_IO_ERROR ->
+ new IOException(appSearchResult.getErrorMessage());
+ case AppSearchResult.RESULT_SECURITY_ERROR ->
+ new SecurityException(appSearchResult.getErrorMessage());
+ default -> new IllegalStateException(appSearchResult.getErrorMessage());
+ };
+ }
+
+ private AndroidFuture<AppSearchSession> getSessionAsync() {
+ return mSettableSessionFuture.thenApply(
+ result -> {
+ if (result.isSuccess()) {
+ return result.getResultValue();
+ } else {
+ throw new RuntimeException(failedResultToException(result));
+ }
+ });
+ }
+
+ /** Gets the schema for a given app search session. */
+ public AndroidFuture<GetSchemaResponse> getSchema() {
+ return getSessionAsync()
+ .thenCompose(
+ session -> {
+ AndroidFuture<AppSearchResult<GetSchemaResponse>>
+ settableSchemaResponse = new AndroidFuture<>();
+ session.getSchema(mExecutor, settableSchemaResponse::complete);
+ return settableSchemaResponse.thenApply(
+ result -> {
+ if (result.isSuccess()) {
+ return result.getResultValue();
+ } else {
+ throw new RuntimeException(
+ failedResultToException(result));
+ }
+ });
+ });
+ }
+
+ /** Sets the schema for a given app search session. */
+ public AndroidFuture<SetSchemaResponse> setSchema(@NonNull SetSchemaRequest setSchemaRequest) {
+ return getSessionAsync()
+ .thenCompose(
+ session -> {
+ AndroidFuture<AppSearchResult<SetSchemaResponse>>
+ settableSchemaResponse = new AndroidFuture<>();
+ session.setSchema(
+ setSchemaRequest,
+ mExecutor,
+ mExecutor,
+ settableSchemaResponse::complete);
+ return settableSchemaResponse.thenApply(
+ result -> {
+ if (result.isSuccess()) {
+ return result.getResultValue();
+ } else {
+ throw new RuntimeException(
+ failedResultToException(result));
+ }
+ });
+ });
+ }
+
+ /** Indexes documents into the AppSearchSession database. */
+ public AndroidFuture<AppSearchBatchResult<String, Void>> put(
+ @NonNull PutDocumentsRequest putDocumentsRequest) {
+ return getSessionAsync()
+ .thenCompose(
+ session -> {
+ AndroidFuture<AppSearchBatchResult<String, Void>> batchResultFuture =
+ new AndroidFuture<>();
+
+ session.put(
+ putDocumentsRequest, mExecutor, batchResultFuture::complete);
+ return batchResultFuture;
+ });
+ }
+
+ /**
+ * Retrieves documents from the open AppSearchSession that match a given query string and type
+ * of search provided.
+ */
+ public AndroidFuture<FutureSearchResults> search(
+ @NonNull String queryExpression, @NonNull SearchSpec searchSpec) {
+ return getSessionAsync()
+ .thenApply(session -> session.search(queryExpression, searchSpec))
+ .thenApply(result -> new FutureSearchResults(result, mExecutor));
+ }
+
+ @Override
+ public void close() throws IOException {
+ try {
+ getSessionAsync().get().close();
+ } catch (Exception ex) {
+ Slog.e(TAG, "Failed to close app search session", ex);
+ }
+ }
+
+ /** A future API wrapper of {@link android.app.appsearch.SearchResults}. */
+ public static class FutureSearchResults {
+ private final SearchResults mSearchResults;
+ private final Executor mExecutor;
+
+ public FutureSearchResults(
+ @NonNull SearchResults searchResults, @NonNull Executor executor) {
+ mSearchResults = Objects.requireNonNull(searchResults);
+ mExecutor = Objects.requireNonNull(executor);
+ }
+
+ public AndroidFuture<List<SearchResult>> getNextPage() {
+ AndroidFuture<AppSearchResult<List<SearchResult>>> nextPageFuture =
+ new AndroidFuture<>();
+
+ mSearchResults.getNextPage(mExecutor, nextPageFuture::complete);
+ return nextPageFuture.thenApply(
+ result -> {
+ if (result.isSuccess()) {
+ return result.getResultValue();
+ } else {
+ throw new RuntimeException(failedResultToException(result));
+ }
+ });
+ }
+ }
+
+ /** A future API to retrieve a document by its id from the local AppSearch session. */
+ public AndroidFuture<GenericDocument> getByDocumentId(
+ @NonNull String documentId, @NonNull String namespace) {
+ Objects.requireNonNull(documentId);
+ Objects.requireNonNull(namespace);
+
+ GetByDocumentIdRequest request =
+ new GetByDocumentIdRequest.Builder(namespace)
+ .addIds(documentId)
+ .build();
+ return getSessionAsync()
+ .thenCompose(
+ session -> {
+ AndroidFuture<AppSearchBatchResult<String, GenericDocument>>
+ batchResultFuture = new AndroidFuture<>();
+ session.getByDocumentId(
+ request,
+ mExecutor,
+ new BatchResultCallbackAdapter<>(batchResultFuture));
+
+ return batchResultFuture.thenApply(
+ batchResult ->
+ getGenericDocumentFromBatchResult(
+ batchResult, documentId));
+ });
+ }
+
+ private static GenericDocument getGenericDocumentFromBatchResult(
+ AppSearchBatchResult<String, GenericDocument> result, String documentId) {
+ if (result.isSuccess()) {
+ return result.getSuccesses().get(documentId);
+ }
+ throw new IllegalArgumentException("No document in the result for id: " + documentId);
+ }
+
+ private static final class BatchResultCallbackAdapter<K, V>
+ implements BatchResultCallback<K, V> {
+ private final AndroidFuture<AppSearchBatchResult<K, V>> mFuture;
+
+ BatchResultCallbackAdapter(AndroidFuture<AppSearchBatchResult<K, V>> future) {
+ mFuture = future;
+ }
+
+ @Override
+ public void onResult(@NonNull AppSearchBatchResult<K, V> result) {
+ mFuture.complete(result);
+ }
+
+ @Override
+ public void onSystemError(Throwable t) {
+ mFuture.completeExceptionally(t);
+ }
+ }
+}
diff --git a/services/appfunctions/java/com/android/server/appfunctions/FutureGlobalSearchSession.java b/services/appfunctions/java/com/android/server/appfunctions/FutureGlobalSearchSession.java
new file mode 100644
index 0000000..0c22624
--- /dev/null
+++ b/services/appfunctions/java/com/android/server/appfunctions/FutureGlobalSearchSession.java
@@ -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.
+ */
+
+package com.android.server.appfunctions;
+
+import android.annotation.NonNull;
+import android.app.appsearch.AppSearchManager;
+import android.app.appsearch.AppSearchResult;
+import android.app.appsearch.GlobalSearchSession;
+import android.app.appsearch.exceptions.AppSearchException;
+import android.app.appsearch.observer.ObserverCallback;
+import android.app.appsearch.observer.ObserverSpec;
+import android.util.Slog;
+
+import com.android.internal.infra.AndroidFuture;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.concurrent.Executor;
+
+/** A wrapper around {@link GlobalSearchSession} that provides a future-based API. */
+public class FutureGlobalSearchSession implements Closeable {
+ private static final String TAG = FutureGlobalSearchSession.class.getSimpleName();
+ private final Executor mExecutor;
+ private final AndroidFuture<AppSearchResult<GlobalSearchSession>> mSettableSessionFuture;
+
+ public FutureGlobalSearchSession(
+ @NonNull AppSearchManager appSearchManager, @NonNull Executor executor) {
+ this.mExecutor = executor;
+ mSettableSessionFuture = new AndroidFuture<>();
+ appSearchManager.createGlobalSearchSession(mExecutor, mSettableSessionFuture::complete);
+ }
+
+ private AndroidFuture<GlobalSearchSession> getSessionAsync() {
+ return mSettableSessionFuture.thenApply(
+ result -> {
+ if (result.isSuccess()) {
+ return result.getResultValue();
+ } else {
+ throw new RuntimeException(
+ FutureAppSearchSession.failedResultToException(result));
+ }
+ });
+ }
+
+ /**
+ * Registers an observer callback for the given target package name.
+ *
+ * @param targetPackageName The package name of the target app.
+ * @param spec The observer spec.
+ * @param executor The executor to run the observer callback on.
+ * @param observer The observer callback to register.
+ * @return A future that completes once the observer is registered.
+ */
+ public AndroidFuture<Void> registerObserverCallbackAsync(
+ String targetPackageName,
+ ObserverSpec spec,
+ Executor executor,
+ ObserverCallback observer) {
+ return getSessionAsync()
+ .thenCompose(
+ session -> {
+ try {
+ session.registerObserverCallback(
+ targetPackageName, spec, executor, observer);
+ return AndroidFuture.completedFuture(null);
+ } catch (AppSearchException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+
+ @Override
+ public void close() throws IOException {
+ try {
+ getSessionAsync().get().close();
+ } catch (Exception ex) {
+ Slog.e(TAG, "Failed to close global search session", ex);
+ }
+ }
+}
diff --git a/services/appfunctions/java/com/android/server/appfunctions/MetadataSyncAdapter.java b/services/appfunctions/java/com/android/server/appfunctions/MetadataSyncAdapter.java
new file mode 100644
index 0000000..be5770b
--- /dev/null
+++ b/services/appfunctions/java/com/android/server/appfunctions/MetadataSyncAdapter.java
@@ -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.server.appfunctions;
+
+import android.annotation.NonNull;
+import android.annotation.WorkerThread;
+import android.app.appsearch.SearchResult;
+import android.app.appsearch.SearchSpec;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.appfunctions.FutureAppSearchSession.FutureSearchResults;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+
+/**
+ * This class implements helper methods for synchronously interacting with AppSearch while
+ * synchronizing AppFunction runtime and static metadata.
+ */
+public class MetadataSyncAdapter {
+ private final FutureAppSearchSession mFutureAppSearchSession;
+ private final Executor mSyncExecutor;
+
+ public MetadataSyncAdapter(
+ @NonNull Executor syncExecutor,
+ @NonNull FutureAppSearchSession futureAppSearchSession) {
+ mSyncExecutor = Objects.requireNonNull(syncExecutor);
+ mFutureAppSearchSession = Objects.requireNonNull(futureAppSearchSession);
+ }
+
+ /**
+ * This method returns a map of package names to a set of function ids that are in the static
+ * metadata but not in the runtime metadata.
+ *
+ * @param staticPackageToFunctionMap A map of package names to a set of function ids from the
+ * static metadata.
+ * @param runtimePackageToFunctionMap A map of package names to a set of function ids from the
+ * runtime metadata.
+ * @return A map of package names to a set of function ids that are in the static metadata but
+ * not in the runtime metadata.
+ */
+ @NonNull
+ @VisibleForTesting
+ static ArrayMap<String, ArraySet<String>> getAddedFunctionsDiffMap(
+ ArrayMap<String, ArraySet<String>> staticPackageToFunctionMap,
+ ArrayMap<String, ArraySet<String>> runtimePackageToFunctionMap) {
+ return getFunctionsDiffMap(staticPackageToFunctionMap, runtimePackageToFunctionMap);
+ }
+
+ /**
+ * This method returns a map of package names to a set of function ids that are in the runtime
+ * metadata but not in the static metadata.
+ *
+ * @param staticPackageToFunctionMap A map of package names to a set of function ids from the
+ * static metadata.
+ * @param runtimePackageToFunctionMap A map of package names to a set of function ids from the
+ * runtime metadata.
+ * @return A map of package names to a set of function ids that are in the runtime metadata but
+ * not in the static metadata.
+ */
+ @NonNull
+ @VisibleForTesting
+ static ArrayMap<String, ArraySet<String>> getRemovedFunctionsDiffMap(
+ ArrayMap<String, ArraySet<String>> staticPackageToFunctionMap,
+ ArrayMap<String, ArraySet<String>> runtimePackageToFunctionMap) {
+ return getFunctionsDiffMap(runtimePackageToFunctionMap, staticPackageToFunctionMap);
+ }
+
+ @NonNull
+ private static ArrayMap<String, ArraySet<String>> getFunctionsDiffMap(
+ ArrayMap<String, ArraySet<String>> packageToFunctionMapA,
+ ArrayMap<String, ArraySet<String>> packageToFunctionMapB) {
+ ArrayMap<String, ArraySet<String>> diffMap = new ArrayMap<>();
+ for (String packageName : packageToFunctionMapA.keySet()) {
+ if (!packageToFunctionMapB.containsKey(packageName)) {
+ diffMap.put(packageName, packageToFunctionMapA.get(packageName));
+ continue;
+ }
+ ArraySet<String> diffFunctions = new ArraySet<>();
+ for (String functionId :
+ Objects.requireNonNull(packageToFunctionMapA.get(packageName))) {
+ if (!Objects.requireNonNull(packageToFunctionMapB.get(packageName))
+ .contains(functionId)) {
+ diffFunctions.add(functionId);
+ }
+ }
+ if (!diffFunctions.isEmpty()) {
+ diffMap.put(packageName, diffFunctions);
+ }
+ }
+ return diffMap;
+ }
+
+ /**
+ * This method returns a map of package names to a set of function ids.
+ *
+ * @param queryExpression The query expression to use when searching for AppFunction metadata.
+ * @param metadataSearchSpec The search spec to use when searching for AppFunction metadata.
+ * @return A map of package names to a set of function ids.
+ * @throws ExecutionException If the future search results fail to execute.
+ * @throws InterruptedException If the future search results are interrupted.
+ */
+ @NonNull
+ @VisibleForTesting
+ @WorkerThread
+ ArrayMap<String, ArraySet<String>> getPackageToFunctionIdMap(
+ @NonNull String queryExpression,
+ @NonNull SearchSpec metadataSearchSpec,
+ @NonNull String propertyFunctionId,
+ @NonNull String propertyPackageName)
+ throws ExecutionException, InterruptedException {
+ ArrayMap<String, ArraySet<String>> packageToFunctionIds = new ArrayMap<>();
+ FutureSearchResults futureSearchResults =
+ mFutureAppSearchSession.search(queryExpression, metadataSearchSpec).get();
+ List<SearchResult> searchResultsList = futureSearchResults.getNextPage().get();
+ // TODO(b/357551503): This could be expensive if we have more functions
+ while (!searchResultsList.isEmpty()) {
+ for (SearchResult searchResult : searchResultsList) {
+ String packageName =
+ searchResult.getGenericDocument().getPropertyString(propertyPackageName);
+ String functionId =
+ searchResult.getGenericDocument().getPropertyString(propertyFunctionId);
+ packageToFunctionIds
+ .computeIfAbsent(packageName, k -> new ArraySet<>())
+ .add(functionId);
+ }
+ searchResultsList = futureSearchResults.getNextPage().get();
+ }
+ return packageToFunctionIds;
+ }
+}
diff --git a/services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCaller.java b/services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCaller.java
index 98903ae..58597c3 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCaller.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCaller.java
@@ -25,7 +25,6 @@
* services are properly unbound after the operation completes or a timeout occurs.
*
* @param <T> Class of wrapped service.
- * @hide
*/
public interface RemoteServiceCaller<T> {
diff --git a/services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCallerImpl.java b/services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCallerImpl.java
index c19a027..eea17ee 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCallerImpl.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCallerImpl.java
@@ -30,27 +30,24 @@
import java.util.function.Function;
/**
- * An implementation of {@link RemoteServiceCaller} that that is based on
- * {@link Context#bindService}.
+ * An implementation of {@link RemoteServiceCaller} that that is based on {@link
+ * Context#bindService}.
*
* @param <T> Class of wrapped service.
- * @hide
*/
public class RemoteServiceCallerImpl<T> implements RemoteServiceCaller<T> {
private static final String TAG = "AppFunctionsServiceCall";
- @NonNull
- private final Context mContext;
- @NonNull
- private final Function<IBinder, T> mInterfaceConverter;
+ @NonNull private final Context mContext;
+ @NonNull private final Function<IBinder, T> mInterfaceConverter;
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final Executor mExecutor;
/**
* @param interfaceConverter A function responsible for converting an IBinder object into the
- * desired service interface.
- * @param executor An Executor instance to dispatch callback.
- * @param context The system context.
+ * desired service interface.
+ * @param executor An Executor instance to dispatch callback.
+ * @param context The system context.
*/
public RemoteServiceCallerImpl(
@NonNull Context context,
diff --git a/services/appfunctions/java/com/android/server/appfunctions/ServiceConfig.java b/services/appfunctions/java/com/android/server/appfunctions/ServiceConfig.java
index 4bc6e70..caa4bf0 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/ServiceConfig.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/ServiceConfig.java
@@ -16,15 +16,11 @@
package com.android.server.appfunctions;
-/**
- * This interface is used to expose configs to the AppFunctionManagerService.
- */
+/** This interface is used to expose configs to the AppFunctionManagerService. */
public interface ServiceConfig {
// TODO(b/357551503): Obtain namespace from DeviceConfig.
String NAMESPACE_APP_FUNCTIONS = "appfunctions";
- /**
- * Returns the maximum time to wait for an app function execution to be complete.
- */
+ /** Returns the maximum time to wait for an app function execution to be complete. */
long getExecuteAppFunctionTimeoutMillis();
}
diff --git a/services/appfunctions/java/com/android/server/appfunctions/ServiceConfigImpl.java b/services/appfunctions/java/com/android/server/appfunctions/ServiceConfigImpl.java
index e090317..f18789b 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/ServiceConfigImpl.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/ServiceConfigImpl.java
@@ -18,21 +18,17 @@
import android.provider.DeviceConfig;
-/**
- * Implementation of {@link ServiceConfig}
- */
+/** Implementation of {@link ServiceConfig} */
public class ServiceConfigImpl implements ServiceConfig {
static final String DEVICE_CONFIG_PROPERTY_EXECUTION_TIMEOUT =
"execute_app_function_timeout_millis";
static final long DEFAULT_EXECUTE_APP_FUNCTION_TIMEOUT_MS = 5000L;
-
@Override
public long getExecuteAppFunctionTimeoutMillis() {
return DeviceConfig.getLong(
NAMESPACE_APP_FUNCTIONS,
DEVICE_CONFIG_PROPERTY_EXECUTION_TIMEOUT,
- DEFAULT_EXECUTE_APP_FUNCTION_TIMEOUT_MS
- );
+ DEFAULT_EXECUTE_APP_FUNCTION_TIMEOUT_MS);
}
}
diff --git a/services/appfunctions/java/com/android/server/appfunctions/ServiceHelper.java b/services/appfunctions/java/com/android/server/appfunctions/ServiceHelper.java
index 6cd87d3..bc7bd2b 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/ServiceHelper.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/ServiceHelper.java
@@ -22,18 +22,16 @@
import com.android.internal.annotations.VisibleForTesting;
-/**
- * Helper interface for AppFunctionService.
- */
+/** Helper interface for AppFunctionService. */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public interface ServiceHelper {
/**
* Resolves the AppFunctionService for the target package.
*
* @param targetPackageName The package name of the target.
- * @param targetUser The user which the caller is requesting to execute as.
+ * @param targetUser The user which the caller is requesting to execute as.
* @return The intent to bind to the target service.
*/
- Intent resolveAppFunctionService(@NonNull String targetPackageName,
- @NonNull UserHandle targetUser);
+ Intent resolveAppFunctionService(
+ @NonNull String targetPackageName, @NonNull UserHandle targetUser);
}
diff --git a/services/appfunctions/java/com/android/server/appfunctions/ServiceHelperImpl.java b/services/appfunctions/java/com/android/server/appfunctions/ServiceHelperImpl.java
index e49fba5..37a3779 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/ServiceHelperImpl.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/ServiceHelperImpl.java
@@ -38,23 +38,23 @@
}
@Override
- public Intent resolveAppFunctionService(@NonNull String targetPackageName,
- @NonNull UserHandle targetUser) {
+ public Intent resolveAppFunctionService(
+ @NonNull String targetPackageName, @NonNull UserHandle targetUser) {
Intent serviceIntent = new Intent(AppFunctionService.SERVICE_INTERFACE);
serviceIntent.setPackage(targetPackageName);
- ResolveInfo resolveInfo = mContext.createContextAsUser(targetUser, /* flags= */ 0)
- .getPackageManager().resolveService(serviceIntent, 0);
+ ResolveInfo resolveInfo =
+ mContext.createContextAsUser(targetUser, /* flags= */ 0)
+ .getPackageManager()
+ .resolveService(serviceIntent, 0);
if (resolveInfo == null || resolveInfo.serviceInfo == null) {
return null;
}
ServiceInfo serviceInfo = resolveInfo.serviceInfo;
- if (!Manifest.permission.BIND_APP_FUNCTION_SERVICE.equals(
- serviceInfo.permission)) {
+ if (!Manifest.permission.BIND_APP_FUNCTION_SERVICE.equals(serviceInfo.permission)) {
return null;
}
- serviceIntent.setComponent(
- new ComponentName(serviceInfo.packageName, serviceInfo.name));
+ serviceIntent.setComponent(new ComponentName(serviceInfo.packageName, serviceInfo.name));
return serviceIntent;
}
diff --git a/services/appfunctions/java/com/android/server/appfunctions/SyncAppSearchCallHelper.java b/services/appfunctions/java/com/android/server/appfunctions/SyncAppSearchCallHelper.java
deleted file mode 100644
index 5dd4c25..0000000
--- a/services/appfunctions/java/com/android/server/appfunctions/SyncAppSearchCallHelper.java
+++ /dev/null
@@ -1,146 +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.server.appfunctions;
-
-import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER;
-
-import android.annotation.FlaggedApi;
-import android.annotation.NonNull;
-import android.annotation.WorkerThread;
-import android.app.appsearch.AppSearchManager;
-import android.app.appsearch.AppSearchManager.SearchContext;
-import android.app.appsearch.AppSearchResult;
-import android.app.appsearch.AppSearchSession;
-import android.app.appsearch.GetSchemaResponse;
-import android.app.appsearch.SetSchemaRequest;
-import android.app.appsearch.SetSchemaResponse;
-import android.util.Slog;
-
-import com.android.internal.infra.AndroidFuture;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.util.Objects;
-import java.util.concurrent.Executor;
-
-/**
- * Helper class for interacting with a system server local appsearch session asynchronously.
- *
- * <p>Converts the AppSearch Callback API to {@link AndroidFuture}.
- */
-@FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER)
-public class SyncAppSearchCallHelper implements Closeable {
- private static final String TAG = SyncAppSearchCallHelper.class.getSimpleName();
- private final Executor mExecutor;
- private final AppSearchManager mAppSearchManager;
- private final AndroidFuture<AppSearchResult<AppSearchSession>> mSettableSessionFuture;
-
- public SyncAppSearchCallHelper(
- @NonNull AppSearchManager appSearchManager,
- @NonNull Executor executor,
- @NonNull SearchContext appSearchContext) {
- Objects.requireNonNull(appSearchManager);
- Objects.requireNonNull(executor);
- Objects.requireNonNull(appSearchContext);
-
- mExecutor = executor;
- mAppSearchManager = appSearchManager;
- mSettableSessionFuture = new AndroidFuture<>();
- mAppSearchManager.createSearchSession(
- appSearchContext, mExecutor, mSettableSessionFuture::complete);
- }
-
- /** Converts a failed app search result codes into an exception. */
- @NonNull
- private static Exception failedResultToException(@NonNull AppSearchResult appSearchResult) {
- return switch (appSearchResult.getResultCode()) {
- case AppSearchResult.RESULT_INVALID_ARGUMENT ->
- new IllegalArgumentException(appSearchResult.getErrorMessage());
- case AppSearchResult.RESULT_IO_ERROR ->
- new IOException(appSearchResult.getErrorMessage());
- case AppSearchResult.RESULT_SECURITY_ERROR ->
- new SecurityException(appSearchResult.getErrorMessage());
- default -> new IllegalStateException(appSearchResult.getErrorMessage());
- };
- }
-
- private AndroidFuture<AppSearchSession> getSessionAsync() {
- return mSettableSessionFuture.thenApply(
- result -> {
- if (result.isSuccess()) {
- return result.getResultValue();
- } else {
- throw new RuntimeException(failedResultToException(result));
- }
- });
- }
-
- /** Gets the schema for a given app search session. */
- public AndroidFuture<GetSchemaResponse> getSchema() {
- return getSessionAsync()
- .thenComposeAsync(
- session -> {
- AndroidFuture<AppSearchResult<GetSchemaResponse>>
- settableSchemaResponse = new AndroidFuture<>();
- session.getSchema(mExecutor, settableSchemaResponse::complete);
- return settableSchemaResponse.thenApply(
- result -> {
- if (result.isSuccess()) {
- return result.getResultValue();
- } else {
- throw new RuntimeException(
- failedResultToException(result));
- }
- });
- },
- mExecutor);
- }
-
- /** Sets the schema for a given app search session. */
- public AndroidFuture<SetSchemaResponse> setSchema(@NonNull SetSchemaRequest setSchemaRequest) {
- return getSessionAsync()
- .thenComposeAsync(
- session -> {
- AndroidFuture<AppSearchResult<SetSchemaResponse>>
- settableSchemaResponse = new AndroidFuture<>();
- session.setSchema(
- setSchemaRequest,
- mExecutor,
- mExecutor,
- settableSchemaResponse::complete);
- return settableSchemaResponse.thenApply(
- result -> {
- if (result.isSuccess()) {
- return result.getResultValue();
- } else {
- throw new RuntimeException(
- failedResultToException(result));
- }
- });
- },
- mExecutor);
- }
-
- @Override
- public void close() throws IOException {
- try {
- getSessionAsync().get().close();
- } catch (Exception ex) {
- Slog.e(TAG, "Failed to close app search session", ex);
- }
- }
-}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index de94715..b53bf98 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -16,6 +16,7 @@
package com.android.server.appwidget;
+import static android.appwidget.flags.Flags.remoteAdapterConversion;
import static android.appwidget.flags.Flags.removeAppWidgetServiceIoFromCriticalPath;
import static android.appwidget.flags.Flags.supportResumeRestoreAfterReboot;
import static android.content.Context.KEYGUARD_SERVICE;
@@ -219,6 +220,15 @@
// See {@link Provider#pendingDeletedWidgetIds}.
private static final String PENDING_DELETED_IDS_ATTR = "pending_deleted_ids";
+ // Hard limit of number of hosts an app can create, note that the app that hosts the widgets
+ // can have multiple instances of {@link AppWidgetHost}, typically in respect to different
+ // surfaces in the host app.
+ // @see AppWidgetHost
+ // @see AppWidgetHost#mHostId
+ private static final int MAX_NUMBER_OF_HOSTS_PER_PACKAGE = 20;
+ // Hard limit of number of widgets can be pinned by a host.
+ private static final int MAX_NUMBER_OF_WIDGETS_PER_HOST = 200;
+
// Handles user and package related broadcasts.
// See {@link #registerBroadcastReceiver}
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -1650,6 +1660,9 @@
public boolean bindRemoteViewsService(String callingPackage, int appWidgetId, Intent intent,
IApplicationThread caller, IBinder activtiyToken, IServiceConnection connection,
long flags) {
+ if (remoteAdapterConversion()) {
+ throw new UnsupportedOperationException("bindRemoteViewsService is deprecated");
+ }
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
Slog.i(TAG, "bindRemoteViewsService() " + userId);
@@ -2280,7 +2293,7 @@
if (host != null) {
return host;
}
-
+ ensureHostCountBeforeAddLocked(id);
host = new Host();
host.id = id;
mHosts.add(host);
@@ -2288,6 +2301,24 @@
return host;
}
+ /**
+ * Ensures that the number of hosts for a package is less than the maximum number of hosts per
+ * package. If the number of hosts is greater than the maximum number of hosts per package, then
+ * removes the oldest host.
+ */
+ private void ensureHostCountBeforeAddLocked(@NonNull final HostId hostId) {
+ final List<Host> hosts = new ArrayList<>();
+ for (Host host : mHosts) {
+ if (host.id.uid == hostId.uid
+ && host.id.packageName.equals(hostId.packageName)) {
+ hosts.add(host);
+ }
+ }
+ while (hosts.size() >= MAX_NUMBER_OF_HOSTS_PER_PACKAGE) {
+ deleteHostLocked(hosts.remove(0));
+ }
+ }
+
private void deleteHostLocked(Host host) {
if (DEBUG) {
Slog.i(TAG, "deleteHostLocked() " + host);
@@ -2373,6 +2404,11 @@
}
@Override
+ public void onNullBinding(ComponentName name) {
+ mContext.unbindService(this);
+ }
+
+ @Override
public void onServiceDisconnected(ComponentName name) {
// Do nothing
}
@@ -2520,6 +2556,11 @@
}
@Override
+ public void onNullBinding(ComponentName name) {
+ mContext.unbindService(this);
+ }
+
+ @Override
public void onServiceDisconnected(android.content.ComponentName name) {
// Do nothing
}
@@ -3578,12 +3619,33 @@
if (DEBUG) {
Slog.i(TAG, "addWidgetLocked() " + widget);
}
+ ensureWidgetCountBeforeAddLocked(widget);
mWidgets.add(widget);
onWidgetProviderAddedOrChangedLocked(widget);
}
/**
+ * Ensures that the widget count for the widget's host is not greater than the maximum
+ * number of widgets per host. If the count is greater than the maximum, removes oldest widgets
+ * from the host until the count is less than or equal to the maximum.
+ */
+ private void ensureWidgetCountBeforeAddLocked(@NonNull final Widget widget) {
+ if (widget.host == null || widget.host.id == null) {
+ return;
+ }
+ final List<Widget> widgetsInSameHost = new ArrayList<>();
+ for (Widget w : mWidgets) {
+ if (w.host != null && widget.host.id.equals(w.host.id)) {
+ widgetsInSameHost.add(w);
+ }
+ }
+ while (widgetsInSameHost.size() >= MAX_NUMBER_OF_WIDGETS_PER_HOST) {
+ removeWidgetLocked(widgetsInSameHost.remove(0));
+ }
+ }
+
+ /**
* Checks if the provider is assigned and updates the mWidgetPackages to track packages
* that have bound widgets.
*/
diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING
index dd4239c..556fae3 100644
--- a/services/core/java/com/android/server/TEST_MAPPING
+++ b/services/core/java/com/android/server/TEST_MAPPING
@@ -201,6 +201,15 @@
"include-filter": "com.android.server.wm.BackgroundActivityStart*"
}
]
+ },
+ {
+ "name": "CtsOsTestCases",
+ "file_patterns": ["StorageManagerService\\.java"],
+ "options": [
+ {
+ "include-filter": "android.os.storage.cts.StorageManagerTest"
+ }
+ ]
}
]
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 79e09d7..7442277 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1732,41 +1732,47 @@
// In the future, we can remove this logic for every notification here and add a
// callback so listeners know when their PhoneStateListener's subId becomes invalid,
// but for now we use the simplest fix.
- if (validatePhoneId(phoneId) && SubscriptionManager.isValidSubscriptionId(subId)) {
+ if (validatePhoneId(phoneId)) {
mServiceState[phoneId] = state;
- for (Record r : mRecords) {
- if (VDBG) {
- log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId
- + " phoneId=" + phoneId + " state=" + state);
- }
- if (r.matchTelephonyCallbackEvent(
- TelephonyCallback.EVENT_SERVICE_STATE_CHANGED)
- && idMatch(r, subId, phoneId)) {
+ if (SubscriptionManager.isValidSubscriptionId(subId)) {
- try {
- ServiceState stateToSend;
- if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
- stateToSend = new ServiceState(state);
- } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
- stateToSend = state.createLocationInfoSanitizedCopy(false);
- } else {
- stateToSend = state.createLocationInfoSanitizedCopy(true);
+ for (Record r : mRecords) {
+ if (VDBG) {
+ log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId
+ + " phoneId=" + phoneId + " state=" + state);
+ }
+ if (r.matchTelephonyCallbackEvent(
+ TelephonyCallback.EVENT_SERVICE_STATE_CHANGED)
+ && idMatch(r, subId, phoneId)) {
+
+ try {
+ ServiceState stateToSend;
+ if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+ stateToSend = new ServiceState(state);
+ } else if(checkCoarseLocationAccess(
+ r, Build.VERSION_CODES.Q)) {
+ stateToSend = state.createLocationInfoSanitizedCopy(false);
+ } else {
+ stateToSend = state.createLocationInfoSanitizedCopy(true);
+ }
+ if (DBG) {
+ log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
+ + " subId=" + subId + " phoneId=" + phoneId
+ + " state=" + stateToSend);
+ }
+ r.callback.onServiceStateChanged(stateToSend);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
}
- if (DBG) {
- log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
- + " subId=" + subId + " phoneId=" + phoneId
- + " state=" + stateToSend);
- }
- r.callback.onServiceStateChanged(stateToSend);
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
}
}
}
+ else {
+ log("notifyServiceStateForSubscriber: INVALID subId=" +subId);
+ }
} else {
- log("notifyServiceStateForSubscriber: INVALID phoneId=" + phoneId
- + " or subId=" + subId);
+ log("notifyServiceStateForSubscriber: INVALID phoneId=" + phoneId);
}
handleRemoveListLocked();
}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 2af5316..765afef 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1773,7 +1773,8 @@
// Create a Session for the target user and pass in the bundle
completeCloningAccount(response, result, account, toAccounts, userFrom);
} else {
- super.onResult(result);
+ // Bundle format is not defined.
+ super.onResultSkipSanitization(result);
}
}
}.bind();
@@ -1860,7 +1861,8 @@
// account to avoid retries?
// TODO: what we do with the visibility?
- super.onResult(result);
+ // Bundle format is not defined.
+ super.onResultSkipSanitization(result);
}
@Override
@@ -2106,6 +2108,7 @@
@Override
public void onResult(Bundle result) {
Bundle.setDefusable(result, true);
+ result = sanitizeBundle(result);
IAccountManagerResponse response = getResponseAndClose();
if (response != null) {
try {
@@ -2456,6 +2459,7 @@
@Override
public void onResult(Bundle result) {
Bundle.setDefusable(result, true);
+ result = sanitizeBundle(result);
if (result != null && result.containsKey(AccountManager.KEY_BOOLEAN_RESULT)
&& !result.containsKey(AccountManager.KEY_INTENT)) {
final boolean removalAllowed = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
@@ -2970,6 +2974,7 @@
@Override
public void onResult(Bundle result) {
Bundle.setDefusable(result, true);
+ result = sanitizeBundle(result);
if (result != null) {
String label = result.getString(AccountManager.KEY_AUTH_TOKEN_LABEL);
Bundle bundle = new Bundle();
@@ -3147,6 +3152,7 @@
@Override
public void onResult(Bundle result) {
Bundle.setDefusable(result, true);
+ result = sanitizeBundle(result);
if (result != null) {
if (result.containsKey(AccountManager.KEY_AUTH_TOKEN_LABEL)) {
Intent intent = newGrantCredentialsPermissionIntent(
@@ -3618,6 +3624,12 @@
@Override
public void onResult(Bundle result) {
Bundle.setDefusable(result, true);
+ Bundle sessionBundle = null;
+ if (result != null) {
+ // Session bundle will be removed from result.
+ sessionBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
+ }
+ result = sanitizeBundle(result);
mNumResults++;
Intent intent = null;
if (result != null) {
@@ -3679,7 +3691,6 @@
// bundle contains data necessary for finishing the session
// later. The session bundle will be encrypted here and
// decrypted later when trying to finish the session.
- Bundle sessionBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
if (sessionBundle != null) {
String accountType = sessionBundle.getString(AccountManager.KEY_ACCOUNT_TYPE);
if (TextUtils.isEmpty(accountType)
@@ -4067,6 +4078,7 @@
@Override
public void onResult(Bundle result) {
Bundle.setDefusable(result, true);
+ result = sanitizeBundle(result);
IAccountManagerResponse response = getResponseAndClose();
if (response == null) {
return;
@@ -4380,6 +4392,7 @@
@Override
public void onResult(Bundle result) {
Bundle.setDefusable(result, true);
+ result = sanitizeBundle(result);
mNumResults++;
if (result == null) {
onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "null bundle");
@@ -4936,6 +4949,68 @@
callback, resultReceiver);
}
+
+ // All keys for Strings passed from AbstractAccountAuthenticator using Bundle.
+ private static final String[] sStringBundleKeys = new String[] {
+ AccountManager.KEY_ACCOUNT_NAME,
+ AccountManager.KEY_ACCOUNT_TYPE,
+ AccountManager.KEY_AUTHTOKEN,
+ AccountManager.KEY_AUTH_TOKEN_LABEL,
+ AccountManager.KEY_ERROR_MESSAGE,
+ AccountManager.KEY_PASSWORD,
+ AccountManager.KEY_ACCOUNT_STATUS_TOKEN};
+
+ /**
+ * Keep only documented fields in a Bundle received from AbstractAccountAuthenticator.
+ */
+ protected static Bundle sanitizeBundle(Bundle bundle) {
+ if (bundle == null) {
+ return null;
+ }
+ Bundle sanitizedBundle = new Bundle();
+ Bundle.setDefusable(sanitizedBundle, true);
+ int updatedKeysCount = 0;
+ for (String stringKey : sStringBundleKeys) {
+ if (bundle.containsKey(stringKey)) {
+ String value = bundle.getString(stringKey);
+ sanitizedBundle.putString(stringKey, value);
+ updatedKeysCount++;
+ }
+ }
+ String key = AbstractAccountAuthenticator.KEY_CUSTOM_TOKEN_EXPIRY;
+ if (bundle.containsKey(key)) {
+ long expiryMillis = bundle.getLong(key, 0L);
+ sanitizedBundle.putLong(key, expiryMillis);
+ updatedKeysCount++;
+ }
+ key = AccountManager.KEY_BOOLEAN_RESULT;
+ if (bundle.containsKey(key)) {
+ boolean booleanResult = bundle.getBoolean(key, false);
+ sanitizedBundle.putBoolean(key, booleanResult);
+ updatedKeysCount++;
+ }
+ key = AccountManager.KEY_ERROR_CODE;
+ if (bundle.containsKey(key)) {
+ int errorCode = bundle.getInt(key, 0);
+ sanitizedBundle.putInt(key, errorCode);
+ updatedKeysCount++;
+ }
+ key = AccountManager.KEY_INTENT;
+ if (bundle.containsKey(key)) {
+ Intent intent = bundle.getParcelable(key, Intent.class);
+ sanitizedBundle.putParcelable(key, intent);
+ updatedKeysCount++;
+ }
+ if (bundle.containsKey(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE)) {
+ // The field is not copied in sanitized bundle.
+ updatedKeysCount++;
+ }
+ if (updatedKeysCount != bundle.size()) {
+ Log.w(TAG, "Size mismatch after sanitizeBundle call.");
+ }
+ return sanitizedBundle;
+ }
+
private abstract class Session extends IAccountAuthenticatorResponse.Stub
implements IBinder.DeathRecipient, ServiceConnection {
private final Object mSessionLock = new Object();
@@ -5226,10 +5301,15 @@
}
}
}
-
@Override
public void onResult(Bundle result) {
Bundle.setDefusable(result, true);
+ result = sanitizeBundle(result);
+ onResultSkipSanitization(result);
+ }
+
+ public void onResultSkipSanitization(Bundle result) {
+ Bundle.setDefusable(result, true);
mNumResults++;
Intent intent = null;
if (result != null) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index d4f729c..3666524 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1516,9 +1516,8 @@
serviceName, FrameworkStatsLog.SERVICE_STATE_CHANGED__STATE__START);
mAm.mBatteryStatsService.noteServiceStartRunning(uid, packageName, serviceName);
final ProcessRecord hostApp = r.app;
- final boolean wasStopped = hostApp == null ? wasStopped(r) : false;
- final boolean firstLaunch =
- hostApp == null ? !mAm.wasPackageEverLaunched(r.packageName, r.userId) : false;
+ final boolean wasStopped = hostApp == null ? r.appInfo.isStopped() : false;
+ final boolean firstLaunch = hostApp == null ? r.appInfo.isNotLaunched() : false;
String error = bringUpServiceLocked(r, service.getFlags(), callerFg,
false /* whileRestarting */,
@@ -4308,9 +4307,8 @@
true, UNKNOWN_ADJ);
}
- final boolean wasStopped = hostApp == null ? wasStopped(s) : false;
- final boolean firstLaunch =
- hostApp == null ? !mAm.wasPackageEverLaunched(s.packageName, s.userId) : false;
+ final boolean wasStopped = hostApp == null ? s.appInfo.isStopped() : false;
+ final boolean firstLaunch = hostApp == null ? s.appInfo.isNotLaunched() : false;
boolean needOomAdj = false;
if (c.hasFlag(Context.BIND_AUTO_CREATE)) {
@@ -9350,8 +9348,4 @@
return mCachedDeviceProvisioningPackage != null
&& mCachedDeviceProvisioningPackage.equals(packageName);
}
-
- private boolean wasStopped(ServiceRecord serviceRecord) {
- return (serviceRecord.appInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0;
- }
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d121535..3c57476 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -299,7 +299,6 @@
import android.content.pm.UserInfo;
import android.content.pm.UserProperties;
import android.content.pm.VersionedPackage;
-import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -2971,10 +2970,6 @@
}
}
- CompatibilityInfo compatibilityInfoForPackage(ApplicationInfo ai) {
- return mAtmInternal.compatibilityInfoForPackage(ai);
- }
-
/**
* Enforces that the uid that calls a method is not an
* {@link UserHandle#isIsolated(int) isolated} uid.
@@ -4635,7 +4630,6 @@
ProtoLog.v(WM_DEBUG_CONFIGURATION, "Binding proc %s with config %s",
processName, app.getWindowProcessController().getConfiguration());
ApplicationInfo appInfo = instr != null ? instr.mTargetInfo : app.info;
- app.setCompat(compatibilityInfoForPackage(appInfo));
ProfilerInfo profilerInfo = mAppProfiler.setupProfilerInfoLocked(thread, app, instr);
@@ -4674,7 +4668,9 @@
checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");
bindApplicationTimeMillis = SystemClock.uptimeMillis();
bindApplicationTimeNanos = SystemClock.uptimeNanos();
- mAtmInternal.preBindApplication(app.getWindowProcessController());
+ final ActivityTaskManagerInternal.PreBindInfo preBindInfo =
+ mAtmInternal.preBindApplication(app.getWindowProcessController(), appInfo);
+ app.setCompat(preBindInfo.compatibilityInfo);
final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
if (mPlatformCompat != null) {
mPlatformCompat.resetReporting(app.info);
@@ -4716,7 +4712,7 @@
enableTrackAllocation,
isRestrictedBackupMode || !normalMode,
app.isPersistent(),
- new Configuration(app.getWindowProcessController().getConfiguration()),
+ preBindInfo.configuration,
app.getCompat(),
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
@@ -5426,7 +5422,9 @@
for (int i=0; i<intents.length; i++) {
Intent intent = intents[i];
if (intent != null) {
- intent.prepareToEnterSystemServer();
+ if (intent.hasFileDescriptors()) {
+ throw new IllegalArgumentException("File descriptors passed in Intent");
+ }
if (type == ActivityManager.INTENT_SENDER_BROADCAST &&
(intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
throw new IllegalArgumentException(
@@ -5459,6 +5457,7 @@
}
}
intents[i] = new Intent(intent);
+ intents[i].removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);
}
}
if (resolvedTypes != null && resolvedTypes.length != intents.length) {
@@ -13591,7 +13590,12 @@
enforceNotIsolatedCaller("startService");
enforceAllowedToStartOrBindServiceIfSdkSandbox(service);
if (service != null) {
- service.prepareToEnterSystemServer();
+ // Refuse possible leaked file descriptors
+ if (service.hasFileDescriptors()) {
+ throw new IllegalArgumentException("File descriptors passed in Intent");
+ }
+ // Remove existing mismatch flag so it can be properly updated later
+ service.removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);
}
if (callingPackage == null) {
@@ -13828,7 +13832,12 @@
enforceAllowedToStartOrBindServiceIfSdkSandbox(service);
if (service != null) {
- service.prepareToEnterSystemServer();
+ // Refuse possible leaked file descriptors
+ if (service.hasFileDescriptors()) {
+ throw new IllegalArgumentException("File descriptors passed in Intent");
+ }
+ // Remove existing mismatch flag so it can be properly updated later
+ service.removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);
}
if (callingPackage == null) {
diff --git a/services/core/java/com/android/server/am/AppStartInfoTracker.java b/services/core/java/com/android/server/am/AppStartInfoTracker.java
index 1b00cec..6aadcdc 100644
--- a/services/core/java/com/android/server/am/AppStartInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppStartInfoTracker.java
@@ -33,6 +33,7 @@
import android.content.pm.PackageManager;
import android.icu.text.SimpleDateFormat;
import android.os.Binder;
+import android.os.Debug;
import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder.DeathRecipient;
@@ -495,6 +496,10 @@
private void addBaseFieldsFromProcessRecord(ApplicationStartInfo start, ProcessRecord app) {
if (app == null) {
+ if (DEBUG) {
+ Slog.w(TAG,
+ "app is null in addBaseFieldsFromProcessRecord: " + Debug.getCallers(4));
+ }
return;
}
final int definingUid = app.getHostingRecord() != null
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 8e87342..955b75d 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -123,31 +123,16 @@
import com.android.server.net.BaseNetworkObserver;
import com.android.server.pm.UserManagerInternal;
import com.android.server.power.optimization.Flags;
-import com.android.server.power.stats.AggregatedPowerStatsConfig;
-import com.android.server.power.stats.AmbientDisplayPowerStatsProcessor;
-import com.android.server.power.stats.AudioPowerStatsProcessor;
import com.android.server.power.stats.BatteryExternalStatsWorker;
import com.android.server.power.stats.BatteryStatsDumpHelperImpl;
import com.android.server.power.stats.BatteryStatsImpl;
import com.android.server.power.stats.BatteryUsageStatsProvider;
-import com.android.server.power.stats.BluetoothPowerStatsProcessor;
-import com.android.server.power.stats.CameraPowerStatsProcessor;
-import com.android.server.power.stats.CpuPowerStatsProcessor;
-import com.android.server.power.stats.CustomEnergyConsumerPowerStatsProcessor;
-import com.android.server.power.stats.FlashlightPowerStatsProcessor;
-import com.android.server.power.stats.GnssPowerStatsProcessor;
-import com.android.server.power.stats.MobileRadioPowerStatsProcessor;
-import com.android.server.power.stats.PhoneCallPowerStatsProcessor;
-import com.android.server.power.stats.PowerStatsAggregator;
-import com.android.server.power.stats.PowerStatsExporter;
+import com.android.server.power.stats.PowerAttributor;
import com.android.server.power.stats.PowerStatsScheduler;
import com.android.server.power.stats.PowerStatsStore;
import com.android.server.power.stats.PowerStatsUidResolver;
-import com.android.server.power.stats.ScreenPowerStatsProcessor;
-import com.android.server.power.stats.SensorPowerStatsProcessor;
import com.android.server.power.stats.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
-import com.android.server.power.stats.VideoPowerStatsProcessor;
-import com.android.server.power.stats.WifiPowerStatsProcessor;
+import com.android.server.power.stats.processor.MultiStatePowerAttributor;
import com.android.server.power.stats.wakeups.CpuWakeupStats;
import java.io.File;
@@ -207,7 +192,7 @@
private final AtomicFile mConfigFile;
private final BatteryStats.BatteryStatsDumpHelper mDumpHelper;
private final PowerStatsUidResolver mPowerStatsUidResolver = new PowerStatsUidResolver();
- private final AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
+ private final PowerAttributor mPowerAttributor;
private volatile boolean mMonitorEnabled = true;
@@ -445,14 +430,12 @@
mStats.startTrackingSystemServerCpuTime();
}
- mAggregatedPowerStatsConfig = createAggregatedPowerStatsConfig();
- mPowerStatsStore = new PowerStatsStore(systemDir, mHandler, mAggregatedPowerStatsConfig);
+ mPowerStatsStore = new PowerStatsStore(systemDir, mHandler);
+ mPowerAttributor = new MultiStatePowerAttributor(mContext, mPowerStatsStore, mPowerProfile,
+ mCpuScalingPolicies, mPowerStatsUidResolver);
mPowerStatsScheduler = createPowerStatsScheduler(mContext);
- PowerStatsExporter powerStatsExporter =
- new PowerStatsExporter(mPowerStatsStore,
- new PowerStatsAggregator(mAggregatedPowerStatsConfig, mStats.getHistory()));
mBatteryUsageStatsProvider = new BatteryUsageStatsProvider(context,
- powerStatsExporter, mPowerProfile, mCpuScalingPolicies,
+ mPowerAttributor, mPowerProfile, mCpuScalingPolicies,
mPowerStatsStore, Clock.SYSTEM_CLOCK);
mStats.saveBatteryUsageStatsOnReset(mBatteryUsageStatsProvider, mPowerStatsStore);
mDumpHelper = new BatteryStatsDumpHelperImpl(mBatteryUsageStatsProvider);
@@ -472,154 +455,11 @@
onAlarmListener, aHandler);
};
return new PowerStatsScheduler(mStats::schedulePowerStatsSampleCollection,
- new PowerStatsAggregator(mAggregatedPowerStatsConfig,
- mStats.getHistory()), aggregatedPowerStatsSpanDuration,
+ mStats.getHistory(), mPowerAttributor, aggregatedPowerStatsSpanDuration,
powerStatsAggregationPeriod, mPowerStatsStore, alarmScheduler, Clock.SYSTEM_CLOCK,
mMonotonicClock, () -> mStats.getHistory().getStartTime(), mHandler);
}
- private AggregatedPowerStatsConfig createAggregatedPowerStatsConfig() {
- AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
- config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_CPU)
- .trackDeviceStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN)
- .trackUidStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN,
- AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
- .setProcessorSupplier(
- () -> new CpuPowerStatsProcessor(mPowerProfile, mCpuScalingPolicies));
-
- config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_SCREEN)
- .trackDeviceStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN)
- .trackUidStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN)
- .setProcessorSupplier(
- () -> new ScreenPowerStatsProcessor(mPowerProfile));
-
- config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY,
- BatteryConsumer.POWER_COMPONENT_SCREEN)
- .setProcessorSupplier(AmbientDisplayPowerStatsProcessor::new);
-
- config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
- .trackDeviceStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN)
- .trackUidStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN,
- AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
- .setProcessorSupplier(
- () -> new MobileRadioPowerStatsProcessor(mPowerProfile));
-
- config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_PHONE,
- BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
- .setProcessorSupplier(PhoneCallPowerStatsProcessor::new);
-
- config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_WIFI)
- .trackDeviceStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN)
- .trackUidStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN,
- AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
- .setProcessorSupplier(
- () -> new WifiPowerStatsProcessor(mPowerProfile));
-
- config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_BLUETOOTH)
- .trackDeviceStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN)
- .trackUidStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN,
- AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
- .setProcessorSupplier(
- () -> new BluetoothPowerStatsProcessor(mPowerProfile));
-
- config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_AUDIO)
- .trackDeviceStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN)
- .trackUidStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN,
- AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
- .setProcessorSupplier(
- () -> new AudioPowerStatsProcessor(mPowerProfile, mPowerStatsUidResolver));
-
- config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_VIDEO)
- .trackDeviceStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN)
- .trackUidStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN,
- AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
- .setProcessorSupplier(
- () -> new VideoPowerStatsProcessor(mPowerProfile, mPowerStatsUidResolver));
-
- config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT)
- .trackDeviceStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN)
- .trackUidStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN,
- AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
- .setProcessorSupplier(
- () -> new FlashlightPowerStatsProcessor(mPowerProfile,
- mPowerStatsUidResolver));
-
- config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_CAMERA)
- .trackDeviceStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN)
- .trackUidStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN,
- AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
- .setProcessorSupplier(
- () -> new CameraPowerStatsProcessor(mPowerProfile, mPowerStatsUidResolver));
-
- config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_GNSS)
- .trackDeviceStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN)
- .trackUidStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN,
- AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
- .setProcessorSupplier(
- () -> new GnssPowerStatsProcessor(mPowerProfile, mPowerStatsUidResolver));
-
- config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_SENSORS)
- .trackDeviceStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN)
- .trackUidStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN,
- AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
- .setProcessorSupplier(() -> new SensorPowerStatsProcessor(
- () -> mContext.getSystemService(SensorManager.class)));
-
- config.trackCustomPowerComponents(CustomEnergyConsumerPowerStatsProcessor::new)
- .trackDeviceStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN)
- .trackUidStates(
- AggregatedPowerStatsConfig.STATE_POWER,
- AggregatedPowerStatsConfig.STATE_SCREEN,
- AggregatedPowerStatsConfig.STATE_PROCESS_STATE);
- return config;
- }
-
private void setPowerStatsThrottlePeriods(BatteryStatsImpl.BatteryStatsConfig.Builder builder,
String configString) {
if (configString == null) {
@@ -664,83 +504,84 @@
}
public void systemServicesReady() {
+ MultiStatePowerAttributor attributor = (MultiStatePowerAttributor) mPowerAttributor;
mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_CPU,
Flags.streamlinedBatteryStats());
- mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+ attributor.setPowerComponentSupported(
BatteryConsumer.POWER_COMPONENT_CPU,
Flags.streamlinedBatteryStats());
mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_SCREEN,
Flags.streamlinedMiscBatteryStats());
- mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+ attributor.setPowerComponentSupported(
BatteryConsumer.POWER_COMPONENT_SCREEN,
Flags.streamlinedMiscBatteryStats());
mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY,
Flags.streamlinedMiscBatteryStats());
- mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+ attributor.setPowerComponentSupported(
BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY,
Flags.streamlinedMiscBatteryStats());
mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,
Flags.streamlinedConnectivityBatteryStats());
- mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+ attributor.setPowerComponentSupported(
BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,
Flags.streamlinedConnectivityBatteryStats());
- mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+ attributor.setPowerComponentSupported(
BatteryConsumer.POWER_COMPONENT_PHONE,
Flags.streamlinedConnectivityBatteryStats());
mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_WIFI,
Flags.streamlinedConnectivityBatteryStats());
- mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+ attributor.setPowerComponentSupported(
BatteryConsumer.POWER_COMPONENT_WIFI,
Flags.streamlinedConnectivityBatteryStats());
mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
Flags.streamlinedConnectivityBatteryStats());
- mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+ attributor.setPowerComponentSupported(
BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
Flags.streamlinedConnectivityBatteryStats());
mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_AUDIO,
Flags.streamlinedMiscBatteryStats());
- mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+ attributor.setPowerComponentSupported(
BatteryConsumer.POWER_COMPONENT_AUDIO,
Flags.streamlinedMiscBatteryStats());
mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_VIDEO,
Flags.streamlinedMiscBatteryStats());
- mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+ attributor.setPowerComponentSupported(
BatteryConsumer.POWER_COMPONENT_VIDEO,
Flags.streamlinedMiscBatteryStats());
mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT,
Flags.streamlinedMiscBatteryStats());
- mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+ attributor.setPowerComponentSupported(
BatteryConsumer.POWER_COMPONENT_FLASHLIGHT,
Flags.streamlinedMiscBatteryStats());
mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_GNSS,
Flags.streamlinedMiscBatteryStats());
- mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+ attributor.setPowerComponentSupported(
BatteryConsumer.POWER_COMPONENT_GNSS,
Flags.streamlinedMiscBatteryStats());
- mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+ attributor.setPowerComponentSupported(
BatteryConsumer.POWER_COMPONENT_SENSORS,
Flags.streamlinedMiscBatteryStats());
mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_CAMERA,
Flags.streamlinedMiscBatteryStats());
- mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+ attributor.setPowerComponentSupported(
BatteryConsumer.POWER_COMPONENT_CAMERA,
Flags.streamlinedMiscBatteryStats());
// By convention POWER_COMPONENT_ANY represents custom Energy Consumers
mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_ANY,
Flags.streamlinedMiscBatteryStats());
- mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+ attributor.setPowerComponentSupported(
BatteryConsumer.POWER_COMPONENT_ANY,
Flags.streamlinedMiscBatteryStats());
diff --git a/services/core/java/com/android/server/am/BroadcastController.java b/services/core/java/com/android/server/am/BroadcastController.java
index 32026b2..f7085b4 100644
--- a/services/core/java/com/android/server/am/BroadcastController.java
+++ b/services/core/java/com/android/server/am/BroadcastController.java
@@ -1808,7 +1808,12 @@
final Intent verifyBroadcastLocked(Intent intent) {
if (intent != null) {
- intent.prepareToEnterSystemServer();
+ // Refuse possible leaked file descriptors
+ if (intent.hasFileDescriptors()) {
+ throw new IllegalArgumentException("File descriptors passed in Intent");
+ }
+ // Remove existing mismatch flag so it can be properly updated later
+ intent.removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);
}
int flags = intent.getFlags();
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index 8fe33d1..9e4666c 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -1005,13 +1005,10 @@
final ApplicationInfo info = ((ResolveInfo) receiver).activityInfo.applicationInfo;
final ComponentName component = ((ResolveInfo) receiver).activityInfo.getComponentName();
- if ((info.flags & ApplicationInfo.FLAG_STOPPED) != 0) {
- queue.setActiveWasStopped(true);
- }
- final int intentFlags = r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND;
- final boolean firstLaunch = !mService.wasPackageEverLaunched(info.packageName, r.userId);
- queue.setActiveFirstLaunch(firstLaunch);
+ queue.setActiveWasStopped(info.isStopped());
+ queue.setActiveFirstLaunch(info.isNotLaunched());
+ final int intentFlags = r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND;
final HostingRecord hostingRecord = new HostingRecord(HostingRecord.HOSTING_TYPE_BROADCAST,
component, r.intent.getAction(), r.getHostingRecordTriggerType());
final boolean isActivityCapable = (r.options != null
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index 1314521..da40826 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -554,13 +554,11 @@
callingProcessState, proc.mState.getCurProcState(),
false, 0L);
} else {
- final boolean stopped =
- (cpr.appInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0;
+ final boolean stopped = cpr.appInfo.isStopped();
final int packageState = stopped
? PROVIDER_ACQUISITION_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_STOPPED
: PROVIDER_ACQUISITION_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL;
- final boolean firstLaunch = !mService.wasPackageEverLaunched(
- cpi.packageName, userId);
+ final boolean firstLaunch = cpr.appInfo.isNotLaunched();
checkTime(startTime, "getContentProviderImpl: before start process");
proc = mService.startProcessLocked(
cpi.processName, cpr.appInfo, false, 0,
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 0e266f5..3f54cfc 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -78,7 +78,6 @@
import static android.os.Process.THREAD_PRIORITY_DISPLAY;
import static android.os.Process.THREAD_PRIORITY_TOP_APP_BOOST;
import static android.os.Process.setProcessGroup;
-import static android.os.Process.setThreadPriority;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKUP;
@@ -447,6 +446,19 @@
long getElapsedRealtimeMillis() {
return SystemClock.elapsedRealtime();
}
+
+ void batchSetOomAdj(ArrayList<ProcessRecord> procsToOomAdj) {
+ ProcessList.batchSetOomAdj(procsToOomAdj);
+ }
+
+ void setOomAdj(int pid, int uid, int adj) {
+ ProcessList.setOomAdj(pid, uid, adj);
+ }
+
+ void setThreadPriority(int tid, int priority) {
+ Process.setThreadPriority(tid, priority);
+ }
+
}
boolean isChangeEnabled(@CachedCompatChangeId int cachedCompatChangeId,
@@ -1126,26 +1138,31 @@
final int numLru = lruList.size();
if (mConstants.USE_TIERED_CACHED_ADJ) {
final long now = mInjector.getUptimeMillis();
+ int uiTargetAdj = 10;
for (int i = numLru - 1; i >= 0; i--) {
ProcessRecord app = lruList.get(i);
final ProcessStateRecord state = app.mState;
final ProcessCachedOptimizerRecord opt = app.mOptRecord;
- if (!app.isKilledByAm() && app.getThread() != null && state.getCurAdj()
- >= UNKNOWN_ADJ) {
+ if (!app.isKilledByAm() && app.getThread() != null
+ && (state.getCurAdj() >= UNKNOWN_ADJ
+ || (state.hasShownUi() && state.getCurAdj() >= CACHED_APP_MIN_ADJ))) {
final ProcessServiceRecord psr = app.mServices;
int targetAdj = CACHED_APP_MIN_ADJ;
if (opt != null && opt.isFreezeExempt()) {
// BIND_WAIVE_PRIORITY and the like get oom_adj 900
targetAdj += 0;
+ } else if (state.hasShownUi() && uiTargetAdj < 15) {
+ // The most recent 5 apps that have shown UI get 910-914
+ targetAdj += uiTargetAdj++;
} else if ((state.getSetAdj() >= CACHED_APP_MIN_ADJ)
&& (state.getLastStateTime()
+ mConstants.TIERED_CACHED_ADJ_DECAY_TIME) < now) {
// Older cached apps get 950
targetAdj += 50;
} else {
- // Newer cached apps get 910
- targetAdj += 10;
+ // Newer cached apps get 920
+ targetAdj += 20;
}
state.setCurRawAdj(targetAdj);
state.setCurAdj(psr.modifyRawOomAdj(targetAdj));
@@ -1431,7 +1448,7 @@
}
if (!mProcsToOomAdj.isEmpty()) {
- ProcessList.batchSetOomAdj(mProcsToOomAdj);
+ mInjector.batchSetOomAdj(mProcsToOomAdj);
mProcsToOomAdj.clear();
}
@@ -3400,7 +3417,7 @@
if (isBatchingOomAdj && mConstants.ENABLE_BATCHING_OOM_ADJ) {
mProcsToOomAdj.add(app);
} else {
- ProcessList.setOomAdj(app.getPid(), app.uid, state.getCurAdj());
+ mInjector.setOomAdj(app.getPid(), app.uid, state.getCurAdj());
}
if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) {
@@ -3460,10 +3477,11 @@
ActivityManagerService.setFifoPriority(app, true /* enable */);
} else {
// Boost priority for top app UI and render threads
- setThreadPriority(app.getPid(), THREAD_PRIORITY_TOP_APP_BOOST);
+ mInjector.setThreadPriority(app.getPid(),
+ THREAD_PRIORITY_TOP_APP_BOOST);
if (renderThreadTid != 0) {
try {
- setThreadPriority(renderThreadTid,
+ mInjector.setThreadPriority(renderThreadTid,
THREAD_PRIORITY_TOP_APP_BOOST);
} catch (IllegalArgumentException e) {
// thread died, ignore
@@ -3477,14 +3495,14 @@
if (app.useFifoUiScheduling()) {
// Reset UI pipeline to SCHED_OTHER
ActivityManagerService.setFifoPriority(app, false /* enable */);
- setThreadPriority(app.getPid(), state.getSavedPriority());
+ mInjector.setThreadPriority(app.getPid(), state.getSavedPriority());
} else {
// Reset priority for top app UI and render threads
- setThreadPriority(app.getPid(), 0);
+ mInjector.setThreadPriority(app.getPid(), 0);
}
if (renderThreadTid != 0) {
- setThreadPriority(renderThreadTid, THREAD_PRIORITY_DISPLAY);
+ mInjector.setThreadPriority(renderThreadTid, THREAD_PRIORITY_DISPLAY);
}
}
} catch (Exception e) {
@@ -3674,7 +3692,7 @@
if (app.useFifoUiScheduling()) {
mService.scheduleAsFifoPriority(app.getPid(), true);
} else {
- setThreadPriority(app.getPid(), THREAD_PRIORITY_TOP_APP_BOOST);
+ mInjector.setThreadPriority(app.getPid(), THREAD_PRIORITY_TOP_APP_BOOST);
}
if (isScreenOnOrAnimatingLocked(state)) {
initialSchedGroup = SCHED_GROUP_TOP_APP;
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index bb0c24b..5b4e573 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -3394,24 +3394,33 @@
hostingRecord.getDefiningUid(), hostingRecord.getDefiningProcessName());
final ProcessStateRecord state = r.mState;
- final boolean wasStopped = (info.flags & ApplicationInfo.FLAG_STOPPED) != 0;
+ final boolean wasStopped = info.isStopped();
// Check if we should mark the processrecord for first launch after force-stopping
if (wasStopped) {
+ boolean wasEverLaunched;
+ if (android.app.Flags.useAppInfoNotLaunched()) {
+ wasEverLaunched = !info.isNotLaunched();
+ } else {
+ wasEverLaunched = mService.getPackageManagerInternal()
+ .wasPackageEverLaunched(r.getApplicationInfo().packageName, r.userId);
+ }
// Check if the hosting record is for an activity or not. Since the stopped
// state tracking is handled differently to avoid WM calling back into AM,
// store the state in the correct record
if (hostingRecord.isTypeActivity()) {
- final boolean wasPackageEverLaunched = mService
- .wasPackageEverLaunched(r.getApplicationInfo().packageName, r.userId);
// If the package was launched in the past but is currently stopped, only then
// should it be considered as force-stopped.
- @WindowProcessController.StoppedState int stoppedState = wasPackageEverLaunched
+ @WindowProcessController.StoppedState int stoppedState = wasEverLaunched
? STOPPED_STATE_FORCE_STOPPED
: STOPPED_STATE_FIRST_LAUNCH;
r.getWindowProcessController().setStoppedState(stoppedState);
} else {
- r.setWasForceStopped(true);
- // first launch is computed just before logging, for non-activity types
+ if (android.app.Flags.useAppInfoNotLaunched()) {
+ // If it was launched before, then it must be a force-stop
+ r.setWasForceStopped(wasEverLaunched);
+ } else {
+ r.setWasForceStopped(true);
+ }
}
}
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 2937307..99c3eca 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -139,6 +139,7 @@
static final String[] sDeviceConfigAconfigScopes = new String[] {
"accessibility",
"android_core_networking",
+ "android_health_services",
"android_sdk",
"android_stylus",
"aoc",
@@ -235,7 +236,6 @@
"wear_connectivity",
"wear_esim_carriers",
"wear_frameworks",
- "wear_health_services",
"wear_media",
"wear_offload",
"wear_security",
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index bdba6bc..b186eaa 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -1978,6 +1978,7 @@
boolean userSwitchUiEnabled;
synchronized (mLock) {
mCurrentUserId = userId;
+ ActivityManager.invalidateGetCurrentUserIdCache();
userSwitchUiEnabled = mUserSwitchUiEnabled;
}
mInjector.updateUserConfiguration();
@@ -2239,6 +2240,7 @@
return true;
}
mTargetUserId = targetUserId;
+ ActivityManager.invalidateGetCurrentUserIdCache();
userSwitchUiEnabled = mUserSwitchUiEnabled;
}
if (userSwitchUiEnabled) {
@@ -2316,6 +2318,7 @@
synchronized (mLock) {
nextUserId = ObjectUtils.getOrElse(mPendingTargetUserIds.poll(), UserHandle.USER_NULL);
mTargetUserId = UserHandle.USER_NULL;
+ ActivityManager.invalidateGetCurrentUserIdCache();
}
if (nextUserId != UserHandle.USER_NULL) {
switchUser(nextUserId);
@@ -3021,6 +3024,9 @@
mInjector.getUserManagerInternal().addUserLifecycleListener(mUserLifecycleListener);
updateProfileRelatedCaches();
mInjector.reportCurWakefulnessUsageEvent();
+
+ // IpcDataCache must be invalidated before it starts caching.
+ ActivityManager.invalidateGetCurrentUserIdCache();
}
// TODO(b/266158156): remove this method if initial system user boot logic is refactored?
@@ -3184,6 +3190,9 @@
@GuardedBy("mLock")
private int getCurrentOrTargetUserIdLU() {
+ // Note: this result is currently cached by ActivityManager.getCurrentUser() - changes to
+ // the logic here may require updating how the cache is invalidated.
+ // See ActivityManager.invalidateGetCurrentUserIdCache() for more details.
return mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId;
}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 154b52b..6ae6f3d 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -33,7 +33,6 @@
import static android.app.AppOpsManager.MODE_ERRORED;
import static android.app.AppOpsManager.MODE_FOREGROUND;
import static android.app.AppOpsManager.MODE_IGNORED;
-import static android.app.AppOpsManager.OP_BLUETOOTH_CONNECT;
import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_CAMERA_SANDBOXED;
import static android.app.AppOpsManager.OP_FLAGS_ALL;
@@ -3115,11 +3114,6 @@
packageName);
}
if (!isIncomingPackageValid(packageName, UserHandle.getUserId(uid))) {
- // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
- if (code == OP_BLUETOOTH_CONNECT) {
- Slog.e(TAG, "noting OP_BLUETOOTH_CONNECT returned MODE_ERRORED as incoming "
- + "package: " + packageName + " and uid: " + uid + " is invalid");
- }
return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag,
packageName);
}
@@ -3149,13 +3143,6 @@
}
} catch (SecurityException e) {
logVerifyAndGetBypassFailure(uid, e, "noteOperation");
- // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
- if (code == OP_BLUETOOTH_CONNECT) {
- Slog.e(TAG, "noting OP_BLUETOOTH_CONNECT returned MODE_ERRORED as"
- + " verifyAndGetBypass returned a SecurityException for package: "
- + packageName + " and uid: " + uid + " and attributionTag: "
- + attributionTag, e);
- }
return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag,
packageName);
}
@@ -3173,17 +3160,6 @@
if (DEBUG) Slog.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
+ " package " + packageName + "flags: " +
AppOpsManager.flagsToString(flags));
- // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
- if (code == OP_BLUETOOTH_CONNECT) {
- Slog.e(TAG, "noting OP_BLUETOOTH_CONNECT returned MODE_ERRORED as"
- + " #getOpsLocked returned null for"
- + " uid: " + uid
- + " packageName: " + packageName
- + " attributionTag: " + attributionTag
- + " pvr.isAttributionTagValid: " + pvr.isAttributionTagValid
- + " pvr.bypass: " + pvr.bypass);
- Slog.e(TAG, "mUidStates.get(" + uid + "): " + mUidStates.get(uid));
- }
return new SyncNotedAppOp(AppOpsManager.MODE_ERRORED, code, attributionTag,
packageName);
}
@@ -3228,11 +3204,6 @@
attributedOp.rejected(uidState.getState(), flags);
scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag,
virtualDeviceId, flags, uidMode);
- // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
- if (code == OP_BLUETOOTH_CONNECT && uidMode == MODE_ERRORED) {
- Slog.e(TAG, "noting OP_BLUETOOTH_CONNECT returned MODE_ERRORED as"
- + " uid mode is MODE_ERRORED");
- }
return new SyncNotedAppOp(uidMode, code, attributionTag, packageName);
}
} else {
@@ -3252,11 +3223,6 @@
attributedOp.rejected(uidState.getState(), flags);
scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag,
virtualDeviceId, flags, mode);
- // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
- if (code == OP_BLUETOOTH_CONNECT && mode == MODE_ERRORED) {
- Slog.e(TAG, "noting OP_BLUETOOTH_CONNECT returned MODE_ERRORED as"
- + " package mode is MODE_ERRORED");
- }
return new SyncNotedAppOp(mode, code, attributionTag, packageName);
}
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 4e24cf3..6daf0d0 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -285,7 +285,6 @@
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.CancellationException;
-import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -411,6 +410,9 @@
/** The controller for the volume UI. */
private final VolumeController mVolumeController = new VolumeController();
+ /** Used only for testing to enable/disable the long press timeout volume actions. */
+ private final AtomicBoolean mVolumeControllerLongPressEnabled = new AtomicBoolean(true);
+
// sendMsg() flags
/** If the msg is already queued, replace it with this one. */
private static final int SENDMSG_REPLACE = 0;
@@ -12554,6 +12556,15 @@
if (DEBUG_VOL) Log.d(TAG, "Volume controller visible: " + visible);
}
+ /** @see AudioManager#setVolumeControllerLongPressTimeoutEnabled(boolean) */
+ @Override
+ @android.annotation.EnforcePermission(MODIFY_AUDIO_SETTINGS_PRIVILEGED)
+ public void setVolumeControllerLongPressTimeoutEnabled(boolean enable) {
+ super.setVolumeControllerLongPressTimeoutEnabled_enforcePermission();
+ mVolumeControllerLongPressEnabled.set(enable);
+ Log.i(TAG, "Volume controller long press timeout enabled: " + enable);
+ }
+
@Override
public void setVolumePolicy(VolumePolicy policy) {
enforceVolumeController("set volume policy");
@@ -12632,7 +12643,9 @@
if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) {
// UI is not visible yet, adjustment is ignored
if (mNextLongPress < now) {
- mNextLongPress = now + mLongPressTimeout;
+ mNextLongPress =
+ now + (mVolumeControllerLongPressEnabled.get() ? mLongPressTimeout
+ : 0);
}
suppress = true;
} else if (mNextLongPress > 0) { // in a long-press
@@ -12699,11 +12712,6 @@
if (mController == null)
return;
try {
- // TODO: remove this when deprecating STREAM_BLUETOOTH_SCO
- if (isStreamBluetoothSco(streamType)) {
- // TODO: notify both sco and voice_call about volume changes
- streamType = AudioSystem.STREAM_BLUETOOTH_SCO;
- }
mController.volumeChanged(streamType, flags);
} catch (RemoteException e) {
Log.w(TAG, "Error calling volumeChanged", e);
@@ -14714,6 +14722,7 @@
@Override
/** @see AudioManager#permissionUpdateBarrier() */
public void permissionUpdateBarrier() {
+ if (!audioserverPermissions()) return;
mAudioSystem.triggerSystemPropertyUpdate(mSysPropListenerNativeHandle);
List<Future> snapshot;
synchronized (mScheduledPermissionTasks) {
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index 70f3193..7e26356 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -1302,7 +1302,7 @@
mEventLogger.enqueue((new EventLogger.StringEvent(
"abandonAudioFocus() from uid/pid " + Binder.getCallingUid()
+ "/" + Binder.getCallingPid()
- + " clientId=" + clientId))
+ + " clientId=" + clientId + " callingPack=" + callingPackageName))
.printLog(TAG));
try {
// this will take care of notifying the new focus owner if needed
diff --git a/services/core/java/com/android/server/biometrics/PreAuthInfo.java b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
index eaf4f81..ac3c028 100644
--- a/services/core/java/com/android/server/biometrics/PreAuthInfo.java
+++ b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
@@ -120,7 +120,9 @@
userId), trustManager)) {
isMandatoryBiometricsAuthentication = true;
promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG);
- promptInfo.setNegativeButtonText(context.getString(R.string.cancel));
+ if (promptInfo.getNegativeButtonText() == null) {
+ promptInfo.setNegativeButtonText(context.getString(R.string.cancel));
+ }
}
final boolean biometricRequested = Utils.isBiometricRequested(promptInfo);
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 907e7c6..86015ac 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -938,7 +938,7 @@
setAmbientLux(mFastAmbientLux);
if (mLoggingEnabled) {
Slog.d(TAG, "updateAmbientLux: "
- + ((mFastAmbientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": "
+ + ((mFastAmbientLux > mPreThresholdLux) ? "Brightened" : "Darkened") + ": "
+ "mAmbientBrighteningThreshold=" + mAmbientBrighteningThreshold + ", "
+ "mAmbientDarkeningThreshold=" + mAmbientDarkeningThreshold + ", "
+ "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer + ", "
diff --git a/services/core/java/com/android/server/display/DisplayBrightnessState.java b/services/core/java/com/android/server/display/DisplayBrightnessState.java
index 334dda0..01bbd2f 100644
--- a/services/core/java/com/android/server/display/DisplayBrightnessState.java
+++ b/services/core/java/com/android/server/display/DisplayBrightnessState.java
@@ -17,6 +17,7 @@
package com.android.server.display;
import android.hardware.display.BrightnessInfo;
+import android.os.PowerManager;
import android.text.TextUtils;
import com.android.server.display.brightness.BrightnessEvent;
@@ -255,7 +256,7 @@
private String mDisplayBrightnessStrategyName;
private boolean mShouldUseAutoBrightness;
private boolean mIsSlowChange;
- private float mMaxBrightness;
+ private float mMaxBrightness = PowerManager.BRIGHTNESS_MAX;
private float mMinBrightness;
private float mCustomAnimationRate = CUSTOM_ANIMATION_RATE_NOT_SET;
private boolean mShouldUpdateScreenBrightnessSetting;
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 99ad65d..ed16b14 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -134,6 +134,7 @@
import android.util.EventLog;
import android.util.IndentingPrintWriter;
import android.util.IntArray;
+import android.util.MathUtils;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
@@ -269,6 +270,7 @@
private final Context mContext;
private final DisplayManagerHandler mHandler;
+ private final HandlerExecutor mHandlerExecutor;
private final Handler mUiHandler;
private final DisplayModeDirector mDisplayModeDirector;
private final ExternalDisplayPolicy mExternalDisplayPolicy;
@@ -315,6 +317,7 @@
public boolean mSafeMode;
// All callback records indexed by calling process id.
+ @GuardedBy("mSyncRoot")
private final SparseArray<CallbackRecord> mCallbacks = new SparseArray<>();
/**
@@ -354,7 +357,7 @@
new CopyOnWriteArrayList<>();
/** All {@link DisplayPowerController}s indexed by {@link LogicalDisplay} ID. */
- private final SparseArray<DisplayPowerControllerInterface> mDisplayPowerControllers =
+ private final SparseArray<DisplayPowerController> mDisplayPowerControllers =
new SparseArray<>();
/** {@link DisplayBlanker} used by all {@link DisplayPowerController}s. */
@@ -602,6 +605,7 @@
mContext = context;
mFlags = injector.getFlags();
mHandler = new DisplayManagerHandler(displayThreadLooper);
+ mHandlerExecutor = new HandlerExecutor(mHandler);
mUiHandler = UiThread.getHandler();
mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);
mLogicalDisplayMapper = new LogicalDisplayMapper(mContext,
@@ -726,7 +730,7 @@
if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) {
return;
}
- final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(
+ final DisplayPowerController dpc = mDisplayPowerControllers.get(
logicalDisplay.getDisplayIdLocked());
if (dpc == null) {
return;
@@ -760,12 +764,13 @@
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
+
ActivityManager activityManager = mContext.getSystemService(ActivityManager.class);
activityManager.addOnUidImportanceListener(mUidImportanceListener, IMPORTANCE_CACHED);
mDeviceStateManager = LocalServices.getService(DeviceStateManagerInternal.class);
mContext.getSystemService(DeviceStateManager.class).registerCallback(
- new HandlerExecutor(mHandler), new DeviceStateListener());
+ mHandlerExecutor, new DeviceStateListener());
mLogicalDisplayMapper.onWindowManagerReady();
scheduleTraversalLocked(false);
@@ -1019,6 +1024,10 @@
private class UidImportanceListener implements ActivityManager.OnUidImportanceListener {
@Override
public void onUidImportance(int uid, int importance) {
+ onUidImportanceInternal(uid, importance);
+ }
+
+ private void onUidImportanceInternal(int uid, int importance) {
synchronized (mPendingCallbackSelfLocked) {
if (importance >= IMPORTANCE_GONE) {
// Clean up as the app is already gone
@@ -1267,6 +1276,9 @@
|| isUidPresentOnDisplayInternal(callingUid, displayId)) {
return info;
}
+ } else if (displayId == Display.DEFAULT_DISPLAY) {
+ Slog.e(TAG, "Default display is null for info request from uid "
+ + callingUid);
}
return null;
}
@@ -2058,7 +2070,7 @@
configurePreferredDisplayModeLocked(display);
}
- DisplayPowerControllerInterface dpc = addDisplayPowerControllerLocked(display);
+ DisplayPowerController dpc = addDisplayPowerControllerLocked(display);
if (dpc != null) {
final int leadDisplayId = display.getLeadDisplayIdLocked();
updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId);
@@ -2067,7 +2079,7 @@
// that the follower display was added before the lead display.
mLogicalDisplayMapper.forEachLocked(d -> {
if (d.getLeadDisplayIdLocked() == displayId) {
- DisplayPowerControllerInterface followerDpc =
+ DisplayPowerController followerDpc =
mDisplayPowerControllers.get(d.getDisplayIdLocked());
if (followerDpc != null) {
updateDisplayPowerControllerLeaderLocked(followerDpc, displayId);
@@ -2151,7 +2163,7 @@
scheduleTraversalLocked(false);
mPersistentDataStore.saveIfNeeded();
- DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
+ DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
if (dpc != null) {
final int leadDisplayId = display.getLeadDisplayIdLocked();
updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId);
@@ -2165,7 +2177,7 @@
}
private void updateDisplayPowerControllerLeaderLocked(
- @NonNull DisplayPowerControllerInterface dpc, int leadDisplayId) {
+ @NonNull DisplayPowerController dpc, int leadDisplayId) {
if (dpc.getLeadDisplayId() == leadDisplayId) {
// Lead display hasn't changed, nothing to do.
return;
@@ -2174,7 +2186,7 @@
// If it has changed, then we need to unregister from the previous leader if there was one.
final int prevLeaderId = dpc.getLeadDisplayId();
if (prevLeaderId != Layout.NO_LEAD_DISPLAY) {
- final DisplayPowerControllerInterface prevLeader =
+ final DisplayPowerController prevLeader =
mDisplayPowerControllers.get(prevLeaderId);
if (prevLeader != null) {
prevLeader.removeDisplayBrightnessFollower(dpc);
@@ -2183,7 +2195,7 @@
// And then, if it's following, register it with the new one.
if (leadDisplayId != Layout.NO_LEAD_DISPLAY) {
- final DisplayPowerControllerInterface newLeader =
+ final DisplayPowerController newLeader =
mDisplayPowerControllers.get(leadDisplayId);
if (newLeader != null) {
newLeader.addDisplayBrightnessFollower(dpc);
@@ -2215,16 +2227,17 @@
if (display.isValidLocked()) {
applyDisplayChangedLocked(display);
}
- return;
+ } else {
+ releaseDisplayAndEmitEvent(display, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
}
- releaseDisplayAndEmitEvent(display, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
+ Slog.i(TAG, "Logical display removed: " + display.getDisplayIdLocked());
}
private void releaseDisplayAndEmitEvent(LogicalDisplay display, int event) {
final int displayId = display.getDisplayIdLocked();
- final DisplayPowerControllerInterface dpc =
+ final DisplayPowerController dpc =
mDisplayPowerControllers.removeReturnOld(displayId);
if (dpc != null) {
updateDisplayPowerControllerLeaderLocked(dpc, Layout.NO_LEAD_DISPLAY);
@@ -2271,7 +2284,7 @@
private void handleLogicalDisplayDeviceStateTransitionLocked(@NonNull LogicalDisplay display) {
final int displayId = display.getDisplayIdLocked();
- final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
+ final DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
if (dpc != null) {
final int leadDisplayId = display.getLeadDisplayIdLocked();
updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId);
@@ -2692,14 +2705,14 @@
if (userId != mCurrentUserId) {
return;
}
- DisplayPowerControllerInterface dpc = getDpcFromUniqueIdLocked(uniqueId);
+ DisplayPowerController dpc = getDpcFromUniqueIdLocked(uniqueId);
if (dpc != null) {
dpc.setBrightnessConfiguration(c, /* shouldResetShortTermModel= */ true);
}
}
}
- private DisplayPowerControllerInterface getDpcFromUniqueIdLocked(String uniqueId) {
+ private DisplayPowerController getDpcFromUniqueIdLocked(String uniqueId) {
final DisplayDevice displayDevice = mDisplayDeviceRepo.getByUniqueIdLocked(uniqueId);
final LogicalDisplay logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayDevice);
if (logicalDisplay != null) {
@@ -2740,7 +2753,7 @@
final BrightnessConfiguration config =
getBrightnessConfigForDisplayWithPdsFallbackLocked(uniqueId, userSerial);
if (config != null) {
- final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(
+ final DisplayPowerController dpc = mDisplayPowerControllers.get(
logicalDisplay.getDisplayIdLocked());
if (dpc != null) {
dpc.setBrightnessConfiguration(config,
@@ -2987,7 +3000,7 @@
void setAutoBrightnessLoggingEnabled(boolean enabled) {
synchronized (mSyncRoot) {
- final DisplayPowerControllerInterface displayPowerController =
+ final DisplayPowerController displayPowerController =
mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY);
if (displayPowerController != null) {
displayPowerController.setAutoBrightnessLoggingEnabled(enabled);
@@ -2997,7 +3010,7 @@
void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) {
synchronized (mSyncRoot) {
- final DisplayPowerControllerInterface displayPowerController =
+ final DisplayPowerController displayPowerController =
mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY);
if (displayPowerController != null) {
displayPowerController.setDisplayWhiteBalanceLoggingEnabled(enabled);
@@ -3023,7 +3036,7 @@
void setAmbientColorTemperatureOverride(float cct) {
synchronized (mSyncRoot) {
- final DisplayPowerControllerInterface displayPowerController =
+ final DisplayPowerController displayPowerController =
mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY);
if (displayPowerController != null) {
displayPowerController.setAmbientColorTemperatureOverride(cct);
@@ -3033,7 +3046,7 @@
void setDockedAndIdleEnabled(boolean enabled, int displayId) {
synchronized (mSyncRoot) {
- final DisplayPowerControllerInterface displayPowerController =
+ final DisplayPowerController displayPowerController =
mDisplayPowerControllers.get(displayId);
if (displayPowerController != null) {
displayPowerController.setAutomaticScreenBrightnessMode(enabled
@@ -3090,6 +3103,7 @@
/**
* Get internal or external viewport. Create it if does not currently exist.
+ *
* @param viewportType - either INTERNAL or EXTERNAL
* @return the viewport with the requested type
*/
@@ -3232,36 +3246,40 @@
// After releasing the lock, send the notifications out.
for (int i = 0; i < mTempCallbacks.size(); i++) {
CallbackRecord callbackRecord = mTempCallbacks.get(i);
- final int uid = callbackRecord.mUid;
- final int pid = callbackRecord.mPid;
- if (isUidCached(uid)) {
- // For cached apps, save the pending event until it becomes non-cached
- synchronized (mPendingCallbackSelfLocked) {
- SparseArray<PendingCallback> pendingCallbacks = mPendingCallbackSelfLocked.get(
- uid);
- if (extraLogging(callbackRecord.mPackageName)) {
- Slog.i(TAG, "Uid is cached: " + uid
- + ", pendingCallbacks: " + pendingCallbacks);
- }
- if (pendingCallbacks == null) {
- pendingCallbacks = new SparseArray<>();
- mPendingCallbackSelfLocked.put(uid, pendingCallbacks);
- }
- PendingCallback pendingCallback = pendingCallbacks.get(pid);
- if (pendingCallback == null) {
- pendingCallbacks.put(pid,
- new PendingCallback(callbackRecord, displayId, event));
- } else {
- pendingCallback.addDisplayEvent(displayId, event);
- }
- }
- } else {
- callbackRecord.notifyDisplayEventAsync(displayId, event);
- }
+ deliverEventInternal(callbackRecord, displayId, event);
}
mTempCallbacks.clear();
}
+ private void deliverEventInternal(CallbackRecord callbackRecord, int displayId, int event) {
+ final int uid = callbackRecord.mUid;
+ final int pid = callbackRecord.mPid;
+ if (isUidCached(uid)) {
+ // For cached apps, save the pending event until it becomes non-cached
+ synchronized (mPendingCallbackSelfLocked) {
+ SparseArray<PendingCallback> pendingCallbacks = mPendingCallbackSelfLocked.get(
+ uid);
+ if (extraLogging(callbackRecord.mPackageName)) {
+ Slog.i(TAG, "Uid is cached: " + uid
+ + ", pendingCallbacks: " + pendingCallbacks);
+ }
+ if (pendingCallbacks == null) {
+ pendingCallbacks = new SparseArray<>();
+ mPendingCallbackSelfLocked.put(uid, pendingCallbacks);
+ }
+ PendingCallback pendingCallback = pendingCallbacks.get(pid);
+ if (pendingCallback == null) {
+ pendingCallbacks.put(pid,
+ new PendingCallback(callbackRecord, displayId, event));
+ } else {
+ pendingCallback.addDisplayEvent(displayId, event);
+ }
+ }
+ } else {
+ callbackRecord.notifyDisplayEventAsync(displayId, event);
+ }
+ }
+
private boolean extraLogging(String packageName) {
return mExtraDisplayEventLogging && mExtraDisplayLoggingPackageName.equals(packageName);
}
@@ -3571,7 +3589,7 @@
}
@RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
- private DisplayPowerControllerInterface addDisplayPowerControllerLocked(
+ private DisplayPowerController addDisplayPowerControllerLocked(
LogicalDisplay display) {
if (mPowerHandler == null) {
// initPowerManagement has not yet been called.
@@ -3585,7 +3603,7 @@
final int userSerial = getUserManager().getUserSerialNumber(mContext.getUserId());
final BrightnessSetting brightnessSetting = new BrightnessSetting(userSerial,
mPersistentDataStore, display, mSyncRoot);
- final DisplayPowerControllerInterface displayPowerController;
+ final DisplayPowerController displayPowerController;
// If display is internal and has a HighBrightnessModeMetadata mapping, use that.
// Or create a new one and use that.
@@ -3764,7 +3782,7 @@
public boolean mWifiDisplayScanRequested;
- CallbackRecord(int pid, int uid, IDisplayManagerCallback callback,
+ CallbackRecord(int pid, int uid, @NonNull IDisplayManagerCallback callback,
@EventsMask long eventsMask) {
mPid = pid;
mUid = uid;
@@ -3792,7 +3810,9 @@
}
/**
- * @return {@code false} if RemoteException happens; otherwise {@code true} for success.
+ * @return {@code false} if RemoteException happens; otherwise {@code true} for
+ * success. This returns true even if the event was deferred because the remote client is
+ * cached.
*/
public boolean notifyDisplayEventAsync(int displayId, @DisplayEvent int event) {
if (!shouldSendEvent(event)) {
@@ -3805,9 +3825,19 @@
"notifyDisplayEventAsync#notSendingEvent=" + event + ",mEventsMask="
+ mEventsMask);
}
+ // The client is not interested in this event, so do nothing.
return true;
}
+ return transmitDisplayEvent(displayId, event);
+ }
+
+ /**
+ * Transmit a single display event. The client is presumed ready. Return true on success
+ * and false if the client died.
+ */
+ private boolean transmitDisplayEvent(int displayId, @DisplayEvent int event) {
+ // The client is ready to receive the event.
try {
mCallback.onDisplayEvent(displayId, event);
return true;
@@ -3819,6 +3849,9 @@
}
}
+ /**
+ * Return true if the client is interested in this event.
+ */
private boolean shouldSendEvent(@DisplayEvent int event) {
final long mask = mEventsMask.get();
switch (event) {
@@ -4373,7 +4406,7 @@
uniqueId, userSerial);
if (config == null) {
// Get default configuration
- DisplayPowerControllerInterface dpc = getDpcFromUniqueIdLocked(uniqueId);
+ DisplayPowerController dpc = getDpcFromUniqueIdLocked(uniqueId);
if (dpc != null) {
config = dpc.getDefaultBrightnessConfiguration();
}
@@ -4386,7 +4419,6 @@
}
-
@Override // Binder call
public BrightnessConfiguration getBrightnessConfigurationForUser(int userId) {
final String uniqueId;
@@ -4427,7 +4459,7 @@
if (display == null || !display.isEnabledLocked()) {
return null;
}
- DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
+ DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
if (dpc != null) {
return dpc.getBrightnessInfo();
}
@@ -4465,14 +4497,16 @@
@Override // Binder call
public void setBrightness(int displayId, float brightness) {
setBrightness_enforcePermission();
- if (!isValidBrightness(brightness)) {
- Slog.w(TAG, "Attempted to set invalid brightness" + brightness);
+ if (Float.isNaN(brightness)) {
+ Slog.w(TAG, "Attempted to set invalid brightness: " + brightness);
return;
}
+ MathUtils.constrain(brightness, PowerManager.BRIGHTNESS_MIN,
+ PowerManager.BRIGHTNESS_MAX);
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
- DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
+ DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
if (dpc != null) {
dpc.setBrightness(brightness);
}
@@ -4492,7 +4526,7 @@
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
- DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
+ DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
if (dpc != null) {
brightness = dpc.getScreenBrightnessSetting();
}
@@ -4764,12 +4798,6 @@
}
}
- private static boolean isValidBrightness(float brightness) {
- return !Float.isNaN(brightness)
- && (brightness >= PowerManager.BRIGHTNESS_MIN)
- && (brightness <= PowerManager.BRIGHTNESS_MAX);
- }
-
@VisibleForTesting
void overrideSensorManager(SensorManager sensorManager) {
synchronized (mSyncRoot) {
@@ -4819,7 +4847,7 @@
id).getPrimaryDisplayDeviceLocked();
final int flags = displayDevice.getDisplayDeviceInfoLocked().flags;
if ((flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
- final DisplayPowerControllerInterface displayPowerController =
+ final DisplayPowerController displayPowerController =
mDisplayPowerControllers.get(id);
if (displayPowerController != null) {
ready &= displayPowerController.requestPowerState(request,
@@ -5200,7 +5228,7 @@
return null;
}
- DisplayPowerControllerInterface displayPowerController =
+ DisplayPowerController displayPowerController =
mDisplayPowerControllers.get(logicalDisplay.getDisplayIdLocked());
if (displayPowerController == null) {
Slog.w(TAG,
diff --git a/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java b/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java
index a188e79..b05a96e 100644
--- a/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java
+++ b/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java
@@ -39,12 +39,12 @@
@Nullable
private final DisplayManagerInternal.DisplayOffloader mDisplayOffloader;
- private final DisplayPowerControllerInterface mDisplayPowerController;
+ private final DisplayPowerController mDisplayPowerController;
private boolean mIsActive;
public DisplayOffloadSessionImpl(
@Nullable DisplayManagerInternal.DisplayOffloader displayOffloader,
- DisplayPowerControllerInterface displayPowerController) {
+ DisplayPowerController displayPowerController) {
mDisplayOffloader = displayOffloader;
mDisplayPowerController = displayPowerController;
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index bf559c1..7c591e3 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -126,7 +126,7 @@
* slower by changing the "animator duration scale" option in Development Settings.
*/
final class DisplayPowerController implements AutomaticBrightnessController.Callbacks,
- DisplayWhiteBalanceController.Callbacks, DisplayPowerControllerInterface {
+ DisplayWhiteBalanceController.Callbacks{
private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked";
private static final String SCREEN_OFF_BLOCKED_TRACE_NAME = "Screen off blocked";
@@ -481,7 +481,7 @@
// DPCs following the brightness of this DPC. This is used in concurrent displays mode - there
// is one lead display, the additional displays follow the brightness value of the lead display.
@GuardedBy("mLock")
- private final SparseArray<DisplayPowerControllerInterface> mDisplayBrightnessFollowers =
+ private final SparseArray<DisplayPowerController> mDisplayBrightnessFollowers =
new SparseArray();
private boolean mBootCompleted;
@@ -679,7 +679,6 @@
/**
* Returns true if the proximity sensor screen-off function is available.
*/
- @Override
public boolean isProximitySensorAvailable() {
return mDisplayPowerProximityStateController.isProximitySensorAvailable();
}
@@ -691,7 +690,6 @@
* @param includePackage if false will null out the package name in events
*/
@Nullable
- @Override
public ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(
@UserIdInt int userId, boolean includePackage) {
if (mBrightnessTracker == null) {
@@ -700,7 +698,6 @@
return mBrightnessTracker.getEvents(userId, includePackage);
}
- @Override
public void onSwitchUser(@UserIdInt int newUserId, int userSerial, float newBrightness) {
Message msg = mHandler.obtainMessage(MSG_SWITCH_USER, newUserId, userSerial, newBrightness);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
@@ -737,7 +734,6 @@
}
@Nullable
- @Override
public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats(
@UserIdInt int userId) {
if (mBrightnessTracker == null) {
@@ -749,7 +745,6 @@
/**
* Persist the brightness slider events and ambient brightness stats to disk.
*/
- @Override
public void persistBrightnessTrackerState() {
if (mBrightnessTracker != null) {
mBrightnessTracker.persistBrightnessTrackerState();
@@ -806,7 +801,6 @@
}
}
- @Override
public void overrideDozeScreenState(int displayState, @Display.StateReason int reason) {
Slog.i(TAG, "New offload doze override: " + Display.stateToString(displayState));
if (mDisplayOffloadSession != null
@@ -833,7 +827,6 @@
}
}
- @Override
public void setDisplayOffloadSession(DisplayOffloadSession session) {
if (session == mDisplayOffloadSession) {
return;
@@ -842,7 +835,6 @@
mDisplayOffloadSession = session;
}
- @Override
public BrightnessConfiguration getDefaultBrightnessConfiguration() {
if (mAutomaticBrightnessController == null) {
return null;
@@ -857,7 +849,6 @@
*
* Make sure DisplayManagerService.mSyncRoot lock is held when this is called
*/
- @Override
public void onDisplayChanged(HighBrightnessModeMetadata hbmMetadata, int leadDisplayId) {
mLeadDisplayId = leadDisplayId;
final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
@@ -939,7 +930,6 @@
* This method should be called when the DisplayPowerController is no longer in use; i.e. when
* the {@link #mDisplayId display} has been removed.
*/
- @Override
public void stop() {
synchronized (mLock) {
clearDisplayBrightnessFollowersLocked();
@@ -1216,7 +1206,6 @@
}
}
- @Override
public void setAutomaticScreenBrightnessMode(
@AutomaticBrightnessController.AutomaticBrightnessMode int mode) {
Message msg = mHandler.obtainMessage();
@@ -1314,7 +1303,7 @@
boolean mustInitialize = false;
mBrightnessReasonTemp.set(null);
mTempBrightnessEvent.reset();
- SparseArray<DisplayPowerControllerInterface> displayBrightnessFollowers;
+ SparseArray<DisplayPowerController> displayBrightnessFollowers;
synchronized (mLock) {
if (mStopped) {
return;
@@ -1547,7 +1536,7 @@
float ambientLux = mAutomaticBrightnessController == null ? 0
: mAutomaticBrightnessController.getAmbientLux();
for (int i = 0; i < displayBrightnessFollowers.size(); i++) {
- DisplayPowerControllerInterface follower = displayBrightnessFollowers.valueAt(i);
+ DisplayPowerController follower = displayBrightnessFollowers.valueAt(i);
follower.setBrightnessToFollow(rawBrightnessState,
mDisplayBrightnessController.convertToNits(rawBrightnessState),
ambientLux, slowChange);
@@ -1904,7 +1893,6 @@
}
}
- @Override
public void updateBrightness() {
sendUpdatePowerState();
}
@@ -1913,12 +1901,10 @@
* Ignores the proximity sensor until the sensor state changes, but only if the sensor is
* currently enabled and forcing the screen to be dark.
*/
- @Override
public void ignoreProximitySensorUntilChanged() {
mDisplayPowerProximityStateController.ignoreProximitySensorUntilChanged();
}
- @Override
public void setBrightnessConfiguration(BrightnessConfiguration c,
boolean shouldResetShortTermModel) {
Message msg = mHandler.obtainMessage(MSG_CONFIGURE_BRIGHTNESS,
@@ -1926,28 +1912,24 @@
msg.sendToTarget();
}
- @Override
public void setTemporaryBrightness(float brightness) {
Message msg = mHandler.obtainMessage(MSG_SET_TEMPORARY_BRIGHTNESS,
Float.floatToIntBits(brightness), 0 /*unused*/);
msg.sendToTarget();
}
- @Override
public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
Message msg = mHandler.obtainMessage(MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT,
Float.floatToIntBits(adjustment), 0 /*unused*/);
msg.sendToTarget();
}
- @Override
public void setBrightnessFromOffload(float brightness) {
Message msg = mHandler.obtainMessage(MSG_SET_BRIGHTNESS_FROM_OFFLOAD,
Float.floatToIntBits(brightness), 0 /*unused*/);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
}
- @Override
public float[] getAutoBrightnessLevels(
@AutomaticBrightnessController.AutomaticBrightnessMode int mode) {
int preset = Settings.System.getIntForUser(mContext.getContentResolver(),
@@ -1956,7 +1938,6 @@
return mDisplayDeviceConfig.getAutoBrightnessBrighteningLevels(mode, preset);
}
- @Override
public float[] getAutoBrightnessLuxLevels(
@AutomaticBrightnessController.AutomaticBrightnessMode int mode) {
int preset = Settings.System.getIntForUser(mContext.getContentResolver(),
@@ -1965,7 +1946,6 @@
return mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(mode, preset);
}
- @Override
public BrightnessInfo getBrightnessInfo() {
synchronized (mCachedBrightnessInfo) {
return new BrightnessInfo(
@@ -1979,7 +1959,6 @@
}
}
- @Override
public void onBootCompleted() {
Message msg = mHandler.obtainMessage(MSG_BOOT_COMPLETED);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
@@ -2243,6 +2222,7 @@
unblockScreenOn();
}
mWindowManagerPolicy.screenTurningOn(mDisplayId, mPendingScreenOnUnblocker);
+ Slog.i(TAG, "Window Manager Policy screenTurningOn complete");
}
// Return true if the screen isn't blocked.
@@ -2495,18 +2475,14 @@
}
}
-
- @Override
public float getScreenBrightnessSetting() {
return mDisplayBrightnessController.getScreenBrightnessSetting();
}
- @Override
public float getDozeBrightnessForOffload() {
return mDisplayBrightnessController.getCurrentBrightness() * mDozeScaleFactor;
}
- @Override
public void setBrightness(float brightness) {
// After HBMController and NBMController migration to Clampers framework
// currentBrightnessMax should be taken from clampers controller
@@ -2515,7 +2491,6 @@
mBrightnessRangeController.getCurrentBrightnessMax());
}
- @Override
public void setBrightness(float brightness, int userSerial) {
// After HBMController and NBMController migration to Clampers framework
// currentBrightnessMax should be taken from clampers controller
@@ -2524,17 +2499,14 @@
mBrightnessRangeController.getCurrentBrightnessMax());
}
- @Override
public int getDisplayId() {
return mDisplayId;
}
- @Override
public int getLeadDisplayId() {
return mLeadDisplayId;
}
- @Override
public void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux,
boolean slowChange) {
mBrightnessRangeController.onAmbientLuxChange(ambientLux);
@@ -2595,16 +2567,14 @@
mAutomaticBrightnessController.getLastSensorTimestamps());
}
- @Override
- public void addDisplayBrightnessFollower(DisplayPowerControllerInterface follower) {
+ public void addDisplayBrightnessFollower(DisplayPowerController follower) {
synchronized (mLock) {
mDisplayBrightnessFollowers.append(follower.getDisplayId(), follower);
sendUpdatePowerStateLocked();
}
}
- @Override
- public void removeDisplayBrightnessFollower(DisplayPowerControllerInterface follower) {
+ public void removeDisplayBrightnessFollower(DisplayPowerController follower) {
synchronized (mLock) {
mDisplayBrightnessFollowers.remove(follower.getDisplayId());
mHandler.postAtTime(() -> follower.setBrightnessToFollow(
@@ -2616,7 +2586,7 @@
@GuardedBy("mLock")
private void clearDisplayBrightnessFollowersLocked() {
for (int i = 0; i < mDisplayBrightnessFollowers.size(); i++) {
- DisplayPowerControllerInterface follower = mDisplayBrightnessFollowers.valueAt(i);
+ DisplayPowerController follower = mDisplayBrightnessFollowers.valueAt(i);
mHandler.postAtTime(() -> follower.setBrightnessToFollow(
PowerManager.BRIGHTNESS_INVALID_FLOAT, BrightnessMappingStrategy.INVALID_NITS,
/* ambientLux= */ 0, /* slowChange= */ false), mClock.uptimeMillis());
@@ -2624,7 +2594,6 @@
mDisplayBrightnessFollowers.clear();
}
- @Override
public void dump(final PrintWriter pw) {
synchronized (mLock) {
pw.println();
@@ -3161,19 +3130,17 @@
}
}
- @Override
public void setAutoBrightnessLoggingEnabled(boolean enabled) {
if (mAutomaticBrightnessController != null) {
mAutomaticBrightnessController.setLoggingEnabled(enabled);
}
}
- @Override // DisplayWhiteBalanceController.Callbacks
+ // DisplayWhiteBalanceController.Callbacks
public void updateWhiteBalance() {
sendUpdatePowerState();
}
- @Override
public void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) {
Message msg = mHandler.obtainMessage();
msg.what = MSG_SET_DWBC_LOGGING_ENABLED;
@@ -3181,7 +3148,6 @@
msg.sendToTarget();
}
- @Override
public void setAmbientColorTemperatureOverride(float cct) {
Message msg = mHandler.obtainMessage();
msg.what = MSG_SET_DWBC_COLOR_OVERRIDE;
diff --git a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java b/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
deleted file mode 100644
index d28578a..0000000
--- a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2022 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;
-
-import android.content.pm.ParceledListSlice;
-import android.hardware.display.AmbientBrightnessDayStats;
-import android.hardware.display.BrightnessChangeEvent;
-import android.hardware.display.BrightnessConfiguration;
-import android.hardware.display.BrightnessInfo;
-import android.hardware.display.DisplayManagerInternal;
-import android.os.PowerManager;
-import android.view.Display;
-
-import java.io.PrintWriter;
-
-/**
- * An interface to manage the display's power state and brightness
- */
-public interface DisplayPowerControllerInterface {
- /**
- * Notified when the display is changed.
- *
- * We use this to apply any changes that might be needed when displays get swapped on foldable
- * devices, when layouts change, etc.
- *
- * Must be called while holding the SyncRoot lock.
- *
- * @param hbmInfo The high brightness mode metadata, like
- * remaining time and hbm events, for the corresponding
- * physical display, to make sure we stay within the safety margins.
- * @param leadDisplayId The display who is considered our "leader" for things like brightness.
- */
- void onDisplayChanged(HighBrightnessModeMetadata hbmInfo, int leadDisplayId);
-
- /**
- * Unregisters all listeners and interrupts all running threads; halting future work.
- *
- * This method should be called when the DisplayPowerController is no longer in use; i.e. when
- * the display has been removed.
- */
- void stop();
-
- /**
- * Used to update the display's BrightnessConfiguration
- * @param config The new BrightnessConfiguration
- */
- void setBrightnessConfiguration(BrightnessConfiguration config,
- boolean shouldResetShortTermModel);
-
- /**
- * Used to set the ambient color temperature of the Display
- * @param ambientColorTemperature The target ambientColorTemperature
- */
- void setAmbientColorTemperatureOverride(float ambientColorTemperature);
-
- /**
- * Used to decide the associated AutomaticBrightnessController's BrightnessMode
- * @param mode The auto-brightness mode
- */
- void setAutomaticScreenBrightnessMode(
- @AutomaticBrightnessController.AutomaticBrightnessMode int mode);
-
- /**
- * Used to enable/disable the logging of the WhileBalance associated entities
- * @param enabled Flag which represents if the logging is the be enabled
- */
- void setDisplayWhiteBalanceLoggingEnabled(boolean enabled);
-
- /**
- * Used to dump the state.
- * @param writer The PrintWriter used to dump the state.
- */
- void dump(PrintWriter writer);
-
- /**
- * Used to get the ambient brightness stats
- */
- ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats(int userId);
-
- /**
- * Get the default brightness configuration
- */
- BrightnessConfiguration getDefaultBrightnessConfiguration();
-
- /**
- * Set the screen brightness of the associated display
- * @param brightness The value to which the brightness is to be set
- */
- void setBrightness(float brightness);
-
- /**
- * Set the screen brightness of the associated display
- * @param brightness The value to which the brightness is to be set
- * @param userSerial The user for which the brightness value is to be set.
- */
- void setBrightness(float brightness, int userSerial);
-
- /**
- * Checks if the proximity sensor is available
- */
- boolean isProximitySensorAvailable();
-
- /**
- * Persist the brightness slider events and ambient brightness stats to disk.
- */
- void persistBrightnessTrackerState();
-
- /**
- * Ignores the proximity sensor until the sensor state changes, but only if the sensor is
- * currently enabled and forcing the screen to be dark.
- */
- void ignoreProximitySensorUntilChanged();
-
- /**
- * Requests a new power state.
- *
- * @param request The requested power state.
- * @param waitForNegativeProximity If true, issues a request to wait for
- * negative proximity before turning the screen back on,
- * assuming the screen was turned off by the proximity sensor.
- * @return True if display is ready, false if there are important changes that must
- * be made asynchronously.
- */
- boolean requestPowerState(DisplayManagerInternal.DisplayPowerRequest request,
- boolean waitForNegativeProximity);
-
- /**
- * Overrides the current doze screen state.
- *
- * @param displayState the new doze display state.
- * @param reason the reason behind the new doze display state.
- */
- void overrideDozeScreenState(int displayState, @Display.StateReason int reason);
-
- void setDisplayOffloadSession(DisplayManagerInternal.DisplayOffloadSession session);
-
- /**
- * Sets up the temporary autobrightness adjustment when the user is yet to settle down to a
- * value.
- */
- void setTemporaryAutoBrightnessAdjustment(float adjustment);
-
- /**
- * Sets temporary brightness from the offload chip until we get a brightness value from
- * the light sensor.
- * @param brightness The brightness value between {@link PowerManager.BRIGHTNESS_MIN} and
- * {@link PowerManager.BRIGHTNESS_MAX}. Values outside of that range will be ignored.
- */
- void setBrightnessFromOffload(float brightness);
-
- /**
- * Gets the screen brightness setting
- */
- float getScreenBrightnessSetting();
-
- /**
- * Gets the brightness value used when the device is in doze
- */
- float getDozeBrightnessForOffload();
-
- /**
- * Sets up the temporary brightness for the associated display
- */
- void setTemporaryBrightness(float brightness);
-
- /**
- * Gets the associated {@link BrightnessInfo}
- */
- BrightnessInfo getBrightnessInfo();
-
- /**
- * Get the {@link BrightnessChangeEvent}s for the specified user.
- */
- ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(int userId, boolean hasUsageStats);
-
- /**
- * Sets up the logging for the associated {@link AutomaticBrightnessController}
- * @param enabled Flag to represent if the logging is to be enabled
- */
- void setAutoBrightnessLoggingEnabled(boolean enabled);
-
- /**
- * Handles the changes to be done to update the brightness when the user is changed
- * @param newUserId The new userId
- * @param userSerial The serial number of the new user
- * @param newBrightness The brightness for the new user
- */
- void onSwitchUser(int newUserId, int userSerial, float newBrightness);
-
- /**
- * Get the ID of the display associated with this DPC.
- * @return The display ID
- */
- int getDisplayId();
-
- /**
- * Get the ID of the display that is the leader of this DPC.
- *
- * Note that this is different than the display associated with the DPC. The leader is another
- * display which we follow for things like brightness.
- *
- * Must be called while holding the SyncRoot lock.
- */
- int getLeadDisplayId();
-
- /**
- * Set the brightness to follow if this is an additional display in a set of concurrent
- * displays.
- * @param leadDisplayBrightness The brightness of the lead display in the set of concurrent
- * displays
- * @param nits The brightness value in nits if the device supports nits. Set to a negative
- * number otherwise.
- * @param ambientLux The lux value that will be passed to {@link HighBrightnessModeController}
- * @param slowChange Indicates whether we should slowly animate to the given brightness value.
- */
- void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux,
- boolean slowChange);
-
- /**
- * Add an additional display that will copy the brightness value from this display. This is used
- * when the device is in concurrent displays mode.
- * @param follower The DPC that should copy the brightness value from this DPC
- */
- void addDisplayBrightnessFollower(DisplayPowerControllerInterface follower);
-
- /**
- * Removes the given display from the list of brightness followers.
- * @param follower The DPC to remove from the followers list
- */
- void removeDisplayBrightnessFollower(DisplayPowerControllerInterface follower);
-
- /**
- * Indicate that boot has been completed and the screen is ready to update.
- */
- void onBootCompleted();
-
- /**
- * Get the brightness levels used to determine automatic brightness based on lux levels.
- * @param mode The auto-brightness mode
- * @return The brightness levels for the specified mode. The values are between
- * {@link PowerManager.BRIGHTNESS_MIN} and {@link PowerManager.BRIGHTNESS_MAX}.
- */
- float[] getAutoBrightnessLevels(
- @AutomaticBrightnessController.AutomaticBrightnessMode int mode);
-
- /**
- * Get the lux levels used to determine automatic brightness.
- * @param mode The auto-brightness mode
- * @return The lux levels for the specified mode
- */
- float[] getAutoBrightnessLuxLevels(
- @AutomaticBrightnessController.AutomaticBrightnessMode int mode);
-}
diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamper.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamper.java
index 40e9198..cf44ac0 100644
--- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamper.java
+++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamper.java
@@ -73,7 +73,6 @@
abstract void stop();
protected enum Type {
- THERMAL,
POWER,
WEAR_BEDTIME_MODE,
}
diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java
index d3be33f..9404034 100644
--- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java
+++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java
@@ -72,6 +72,8 @@
private final List<DisplayDeviceDataListener> mDisplayDeviceDataListeners = new ArrayList<>();
private final List<StatefulModifier> mStatefulModifiers = new ArrayList<>();
private final List<UserSwitchListener> mUserSwitchListeners = new ArrayList<>();
+ private final List<DeviceConfigListener> mDeviceConfigListeners = new ArrayList<>();
+
private ModifiersAggregatedState mModifiersAggregatedState = new ModifiersAggregatedState();
private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener;
@@ -144,9 +146,14 @@
if (m instanceof UserSwitchListener l) {
mUserSwitchListeners.add(l);
}
+ if (m instanceof DeviceConfigListener l) {
+ mDeviceConfigListeners.add(l);
+ }
});
- mOnPropertiesChangedListener =
- properties -> mClampers.forEach(BrightnessClamper::onDeviceConfigChanged);
+ mOnPropertiesChangedListener = properties -> {
+ mClampers.forEach(BrightnessClamper::onDeviceConfigChanged);
+ mDeviceConfigListeners.forEach(DeviceConfigListener::onDeviceConfigChanged);
+ };
mLightSensorController.configure(data.getAmbientLightSensor(), data.getDisplayId());
start();
}
@@ -209,8 +216,6 @@
private int getBrightnessMaxReason() {
if (mClamperType == null) {
return BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE;
- } else if (mClamperType == Type.THERMAL) {
- return BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL;
} else if (mClamperType == Type.POWER) {
return BrightnessInfo.BRIGHTNESS_MAX_REASON_POWER_IC;
} else if (mClamperType == Type.WEAR_BEDTIME_MODE) {
@@ -225,7 +230,7 @@
* Called when the user switches.
*/
public void onUserSwitch() {
- mUserSwitchListeners.forEach(listener -> listener.onSwitchUser());
+ mUserSwitchListeners.forEach(UserSwitchListener::onSwitchUser);
}
/**
@@ -294,11 +299,14 @@
state2.mMaxDesiredHdrRatio)
|| !BrightnessSynchronizer.floatEquals(state1.mMaxHdrBrightness,
state2.mMaxHdrBrightness)
- || state1.mSdrHdrRatioSpline != state2.mSdrHdrRatioSpline;
+ || state1.mSdrHdrRatioSpline != state2.mSdrHdrRatioSpline
+ || state1.mMaxBrightnessReason != state2.mMaxBrightnessReason
+ || !BrightnessSynchronizer.floatEquals(state1.mMaxBrightness,
+ state2.mMaxBrightness);
}
private void start() {
- if (!mClampers.isEmpty()) {
+ if (!mClampers.isEmpty() || !mDeviceConfigListeners.isEmpty()) {
mDeviceConfigParameterProvider.addOnPropertiesChangedListener(
mExecutor, mOnPropertiesChangedListener);
}
@@ -333,8 +341,7 @@
ClamperChangeListener clamperChangeListener, DisplayDeviceData data,
DisplayManagerFlags flags, Context context, float currentBrightness) {
List<BrightnessClamper<? super DisplayDeviceData>> clampers = new ArrayList<>();
- clampers.add(
- new BrightnessThermalClamper(handler, clamperChangeListener, data));
+
if (flags.isPowerThrottlingClamperEnabled()) {
// Check if power-throttling config is present.
PowerThrottlingConfigData configData = data.getPowerThrottlingConfigData();
@@ -354,6 +361,8 @@
Handler handler, ClamperChangeListener listener,
DisplayDeviceData data) {
List<BrightnessStateModifier> modifiers = new ArrayList<>();
+ modifiers.add(new BrightnessThermalModifier(handler, listener, data));
+
modifiers.add(new DisplayDimModifier(context));
modifiers.add(new BrightnessLowPowerModeModifier());
if (flags.isEvenDimmerEnabled() && data.mDisplayDeviceConfig.isEvenDimmerAvailable()) {
@@ -384,7 +393,7 @@
/**
* Config Data for clampers/modifiers
*/
- public static class DisplayDeviceData implements BrightnessThermalClamper.ThermalData,
+ public static class DisplayDeviceData implements BrightnessThermalModifier.ThermalData,
BrightnessPowerClamper.PowerData,
BrightnessWearBedtimeModeClamper.WearBedtimeModeData {
@NonNull
@@ -498,13 +507,23 @@
}
/**
+ * Modifier should implement this interface in order to receive device config updates
+ */
+ interface DeviceConfigListener {
+ void onDeviceConfigChanged();
+ }
+
+ /**
* StatefulModifiers contribute to AggregatedState, that is used to decide if brightness
- * adjustement is needed
+ * adjustment is needed
*/
public static class ModifiersAggregatedState {
float mMaxDesiredHdrRatio = HdrBrightnessModifier.DEFAULT_MAX_HDR_SDR_RATIO;
float mMaxHdrBrightness = PowerManager.BRIGHTNESS_MAX;
@Nullable
Spline mSdrHdrRatioSpline = null;
+ @BrightnessInfo.BrightnessMaxReason
+ int mMaxBrightnessReason = BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE;
+ float mMaxBrightness = PowerManager.BRIGHTNESS_MAX;
}
}
diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalClamper.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalModifier.java
similarity index 77%
rename from services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalClamper.java
rename to services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalModifier.java
index 4498258..21ef309 100644
--- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalClamper.java
+++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalModifier.java
@@ -22,6 +22,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.hardware.display.BrightnessInfo;
+import android.hardware.display.DisplayManagerInternal;
import android.os.Handler;
import android.os.IThermalEventListener;
import android.os.IThermalService;
@@ -33,8 +35,10 @@
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData;
import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel;
+import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.config.SensorData;
import com.android.server.display.feature.DeviceConfigParameterProvider;
import com.android.server.display.utils.DeviceConfigParsingUtils;
@@ -43,12 +47,15 @@
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function;
-class BrightnessThermalClamper extends
- BrightnessClamper<BrightnessThermalClamper.ThermalData> {
+class BrightnessThermalModifier implements BrightnessStateModifier,
+ BrightnessClamperController.DisplayDeviceDataListener,
+ BrightnessClamperController.StatefulModifier,
+ BrightnessClamperController.DeviceConfigListener {
private static final String TAG = "BrightnessThermalClamper";
@NonNull
@@ -58,6 +65,11 @@
// data from DeviceConfig, for all displays, for all dataSets
// mapOf(uniqueDisplayId to mapOf(dataSetId to ThermalBrightnessThrottlingData))
@NonNull
+ protected final Handler mHandler;
+ @NonNull
+ protected final BrightnessClamperController.ClamperChangeListener mChangeListener;
+
+ @NonNull
private Map<String, Map<String, ThermalBrightnessThrottlingData>>
mThermalThrottlingDataOverride = Map.of();
// data from DisplayDeviceConfig, for particular display+dataSet
@@ -73,6 +85,8 @@
private String mDataId = null;
@Temperature.ThrottlingStatus
private int mThrottlingStatus = Temperature.THROTTLING_NONE;
+ private float mBrightnessCap = PowerManager.BRIGHTNESS_MAX;
+ private boolean mApplied = false;
private final BiFunction<String, String, ThrottlingLevel> mDataPointMapper = (key, value) -> {
try {
@@ -88,53 +102,51 @@
mDataSetMapper = ThermalBrightnessThrottlingData::create;
- BrightnessThermalClamper(Handler handler, ClamperChangeListener listener,
- ThermalData thermalData) {
- this(new Injector(), handler, listener, thermalData);
+ BrightnessThermalModifier(Handler handler, ClamperChangeListener listener,
+ BrightnessClamperController.DisplayDeviceData data) {
+ this(new Injector(), handler, listener, data);
}
@VisibleForTesting
- BrightnessThermalClamper(Injector injector, Handler handler,
- ClamperChangeListener listener, ThermalData thermalData) {
- super(handler, listener);
+ BrightnessThermalModifier(Injector injector, @NonNull Handler handler,
+ @NonNull ClamperChangeListener listener,
+ @NonNull BrightnessClamperController.DisplayDeviceData data) {
+ mHandler = handler;
+ mChangeListener = listener;
mConfigParameterProvider = injector.getDeviceConfigParameterProvider();
mThermalStatusObserver = new ThermalStatusObserver(injector, handler);
mHandler.post(() -> {
- setDisplayData(thermalData);
- loadOverrideData();
- });
-
- }
-
- @Override
- @NonNull
- Type getType() {
- return Type.THERMAL;
- }
-
- @Override
- void onDeviceConfigChanged() {
- mHandler.post(() -> {
- loadOverrideData();
- recalculateActiveData();
- });
- }
-
- @Override
- void onDisplayChanged(ThermalData data) {
- mHandler.post(() -> {
setDisplayData(data);
- recalculateActiveData();
+ loadOverrideData();
});
}
+ //region BrightnessStateModifier
+ @Override
+ public void apply(DisplayManagerInternal.DisplayPowerRequest request,
+ DisplayBrightnessState.Builder stateBuilder) {
+ if (stateBuilder.getMaxBrightness() > mBrightnessCap) {
+ stateBuilder.setMaxBrightness(mBrightnessCap);
+ stateBuilder.setBrightness(Math.min(stateBuilder.getBrightness(), mBrightnessCap));
+ stateBuilder.setBrightnessMaxReason(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL);
+ stateBuilder.getBrightnessReason().addModifier(BrightnessReason.MODIFIER_THROTTLED);
+ // set fast change only when modifier is activated.
+ // this will allow auto brightness to apply slow change even when modifier is active
+ if (!mApplied) {
+ stateBuilder.setIsSlowChange(false);
+ }
+ mApplied = true;
+ } else {
+ mApplied = false;
+ }
+ }
@Override
- void stop() {
+ public void stop() {
mThermalStatusObserver.stopObserving();
}
@Override
- void dump(PrintWriter writer) {
+ public void dump(PrintWriter writer) {
writer.println("BrightnessThermalClamper:");
writer.println(" mThrottlingStatus: " + mThrottlingStatus);
writer.println(" mUniqueDisplayId: " + mUniqueDisplayId);
@@ -142,10 +154,53 @@
writer.println(" mDataOverride: " + mThermalThrottlingDataOverride);
writer.println(" mDataFromDeviceConfig: " + mThermalThrottlingDataFromDeviceConfig);
writer.println(" mDataActive: " + mThermalThrottlingDataActive);
+ writer.println(" mBrightnessCap:" + mBrightnessCap);
+ writer.println(" mApplied:" + mApplied);
mThermalStatusObserver.dump(writer);
- super.dump(writer);
}
+ @Override
+ public boolean shouldListenToLightSensor() {
+ return false;
+ }
+
+ @Override
+ public void setAmbientLux(float lux) {
+ // noop
+ }
+ //endregion
+
+ //region DisplayDeviceDataListener
+ @Override
+ public void onDisplayChanged(BrightnessClamperController.DisplayDeviceData data) {
+ mHandler.post(() -> {
+ setDisplayData(data);
+ recalculateActiveData();
+ });
+ }
+ //endregion
+
+ //region StatefulModifier
+ @Override
+ public void applyStateChange(
+ BrightnessClamperController.ModifiersAggregatedState aggregatedState) {
+ if (aggregatedState.mMaxBrightness > mBrightnessCap) {
+ aggregatedState.mMaxBrightness = mBrightnessCap;
+ aggregatedState.mMaxBrightnessReason = BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL;
+ }
+ }
+ //endregion
+
+ //region DeviceConfigListener
+ @Override
+ public void onDeviceConfigChanged() {
+ mHandler.post(() -> {
+ loadOverrideData();
+ recalculateActiveData();
+ });
+ }
+ //endregion
+
private void recalculateActiveData() {
if (mUniqueDisplayId == null || mDataId == null) {
return;
@@ -176,14 +231,11 @@
private void recalculateBrightnessCap() {
float brightnessCap = PowerManager.BRIGHTNESS_MAX;
- boolean isActive = false;
-
if (mThermalThrottlingDataActive != null) {
// Throttling levels are sorted by increasing severity
for (ThrottlingLevel level : mThermalThrottlingDataActive.throttlingLevels) {
if (level.thermalStatus <= mThrottlingStatus) {
brightnessCap = level.brightness;
- isActive = true;
} else {
// Throttling levels that are greater than the current status are irrelevant
break;
@@ -191,9 +243,8 @@
}
}
- if (brightnessCap != mBrightnessCap || mIsActive != isActive) {
+ if (brightnessCap != mBrightnessCap) {
mBrightnessCap = brightnessCap;
- mIsActive = isActive;
mChangeListener.onChanged();
}
}
@@ -205,7 +256,6 @@
}
}
-
private final class ThermalStatusObserver extends IThermalEventListener.Stub {
private final Injector mInjector;
private final Handler mHandler;
@@ -228,7 +278,7 @@
String curType = mObserverTempSensor.type;
mObserverTempSensor = tempSensor;
- if (curType.equals(tempSensor.type)) {
+ if (Objects.equals(curType, tempSensor.type)) {
Slog.d(TAG, "Thermal status observer already started");
return;
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
index 234d6d3..236333e 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
@@ -53,6 +53,10 @@
// Default state used in common by all the feature actions.
protected static final int STATE_NONE = 0;
+ // Delay to query avr's audio status, some avrs could report the old volume first. It could
+ // show inverse mute state on TV.
+ protected static final long DELAY_GIVE_AUDIO_STATUS = 500;
+
// Internal state indicating the progress of action.
protected int mState = STATE_NONE;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 81c30dd..101596d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -116,11 +116,11 @@
private boolean mWasActiveSourceSetToConnectedDevice = false;
@VisibleForTesting
- protected boolean getWasActiveSourceSetToConnectedDevice() {
+ protected boolean getWasActivePathSetToConnectedDevice() {
return mWasActiveSourceSetToConnectedDevice;
}
- protected void setWasActiveSourceSetToConnectedDevice(
+ protected void setWasActivePathSetToConnectedDevice(
boolean wasActiveSourceSetToConnectedDevice) {
mWasActiveSourceSetToConnectedDevice = wasActiveSourceSetToConnectedDevice;
}
@@ -404,6 +404,15 @@
}
}
+ @Override
+ void setActivePath(int path) {
+ super.setActivePath(path);
+ if (path != Constants.INVALID_PHYSICAL_ADDRESS
+ && path != Constants.TV_PHYSICAL_ADDRESS) {
+ setWasActivePathSetToConnectedDevice(true);
+ }
+ }
+
@ServiceThreadOnly
void updateActiveInput(int path, boolean notifyInputChange) {
assertRunOnServiceThread();
@@ -512,7 +521,6 @@
|| info.getDeviceType() == HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM) {
mService.getHdmiCecNetwork().updateDevicePowerStatus(logicalAddress,
HdmiControlManager.POWER_STATUS_ON);
- setWasActiveSourceSetToConnectedDevice(true);
ActiveSource activeSource = ActiveSource.of(logicalAddress, physicalAddress);
ActiveSourceHandler.create(this, null).process(activeSource, info.getDeviceType());
} else {
@@ -528,16 +536,16 @@
protected int handleStandby(HdmiCecMessage message) {
assertRunOnServiceThread();
- // If a device has previously asserted the active source status, ignore <Standby> from
- // non-active source.
- if (getWasActiveSourceSetToConnectedDevice()
+ // If the TV has previously changed the active path, ignore <Standby> from non-active
+ // source.
+ if (getWasActivePathSetToConnectedDevice()
&& getActiveSource().logicalAddress != message.getSource()) {
Slog.d(TAG, "<Standby> was not sent by the current active source, ignoring."
+ " Current active source has logical address "
+ getActiveSource().logicalAddress);
return Constants.HANDLED;
}
- setWasActiveSourceSetToConnectedDevice(false);
+ setWasActivePathSetToConnectedDevice(false);
return super.handleStandby(message);
}
@@ -1142,6 +1150,13 @@
return Constants.ABORT_REFUSED;
}
+ if (mArcEstablished) {
+ HdmiLogger.debug("ARC is already established.");
+ HdmiCecMessage command = HdmiCecMessageBuilder.buildReportArcInitiated(
+ getDeviceInfo().getLogicalAddress(), message.getSource());
+ mService.sendCecCommand(command);
+ return Constants.HANDLED;
+ }
// In case where <Initiate Arc> is started by <Request ARC Initiation>, this message is
// handled in RequestArcInitiationAction as well.
SetArcTransmissionStateAction action = new SetArcTransmissionStateAction(this,
@@ -1509,7 +1524,7 @@
invokeStandbyCompletedCallback(callback);
return;
}
- setWasActiveSourceSetToConnectedDevice(false);
+ setWasActivePathSetToConnectedDevice(false);
boolean sendStandbyOnSleep =
mService.getHdmiCecConfig().getIntValue(
HdmiControlManager.CEC_SETTING_NAME_TV_SEND_STANDBY_ON_SLEEP)
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 3c7b9d3..271836a 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1638,6 +1638,10 @@
mHandler.post(new WorkSourceUidPreservingRunnable(runnable));
}
+ void runOnServiceThreadDelayed(Runnable runnable, long delay) {
+ mHandler.postDelayed(new WorkSourceUidPreservingRunnable(runnable), delay);
+ }
+
private void assertRunOnServiceThread() {
if (Looper.myLooper() != mHandler.getLooper()) {
throw new IllegalStateException("Should run on service thread.");
diff --git a/services/core/java/com/android/server/hdmi/RequestSadAction.java b/services/core/java/com/android/server/hdmi/RequestSadAction.java
index 0188e96..2566300 100644
--- a/services/core/java/com/android/server/hdmi/RequestSadAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestSadAction.java
@@ -19,6 +19,8 @@
import android.hardware.hdmi.HdmiControlManager;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -36,7 +38,8 @@
// State in which the action is waiting for <Report Short Audio Descriptor>.
private static final int STATE_WAITING_FOR_REPORT_SAD = 1;
private static final int MAX_SAD_PER_REQUEST = 4;
- private static final int RETRY_COUNTER_MAX = 1;
+ @VisibleForTesting
+ public static final int RETRY_COUNTER_MAX = 3;
private final int mTargetAddress;
private final RequestSadCallback mCallback;
private final List<Integer> mCecCodecsToQuery = new ArrayList<>();
diff --git a/services/core/java/com/android/server/hdmi/RoutingControlAction.java b/services/core/java/com/android/server/hdmi/RoutingControlAction.java
index 0c4fb26..d48957b 100644
--- a/services/core/java/com/android/server/hdmi/RoutingControlAction.java
+++ b/services/core/java/com/android/server/hdmi/RoutingControlAction.java
@@ -44,7 +44,8 @@
static final int STATE_WAIT_FOR_ROUTING_INFORMATION = 1;
// Time out in millseconds used for <Routing Information>
- private static final int TIMEOUT_ROUTING_INFORMATION_MS = 1000;
+ @VisibleForTesting
+ static final int TIMEOUT_ROUTING_INFORMATION_MS = 1000;
// If set to true, call {@link HdmiControlService#invokeInputChangeListener()} when
// the routing control/active source change happens. The listener should be called if
diff --git a/services/core/java/com/android/server/hdmi/SendKeyAction.java b/services/core/java/com/android/server/hdmi/SendKeyAction.java
index 7e18d84..11682f6 100644
--- a/services/core/java/com/android/server/hdmi/SendKeyAction.java
+++ b/services/core/java/com/android/server/hdmi/SendKeyAction.java
@@ -180,15 +180,22 @@
&& localDevice().getService().isAbsoluteVolumeBehaviorEnabled()) {
sendCommand(HdmiCecMessageBuilder.buildUserControlReleased(getSourceAddress(),
mTargetAddress),
- __ -> sendCommand(HdmiCecMessageBuilder.buildGiveAudioStatus(
- getSourceAddress(),
- localDevice().findAudioReceiverAddress())));
+ __ -> queryAvrAudioStatus());
} else {
sendCommand(HdmiCecMessageBuilder.buildUserControlReleased(getSourceAddress(),
mTargetAddress));
}
}
+ private void queryAvrAudioStatus() {
+ localDevice().mService.runOnServiceThreadDelayed(
+ () -> sendCommand(HdmiCecMessageBuilder.buildGiveAudioStatus(
+ getSourceAddress(),
+ localDevice().findAudioReceiverAddress())),
+ DELAY_GIVE_AUDIO_STATUS);
+
+ }
+
@Override
public boolean processCommand(HdmiCecMessage cmd) {
// Send key action doesn't need any incoming CEC command, hence does not consume it.
diff --git a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
index 5ab22e1..e6abcb9 100644
--- a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
+++ b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
@@ -60,6 +60,12 @@
boolean start() {
// Seq #37.
if (mEnabled) {
+ // Avoid triggering duplicate RequestSadAction events.
+ // This could lead to unexpected responses from the AVR and cause the TV to receive data
+ // out of order. The SAD report does not provide information about the order of events.
+ if ((tv().hasAction(RequestSadAction.class))) {
+ return true;
+ }
// Request SADs before enabling ARC
RequestSadAction action = new RequestSadAction(
localDevice(), Constants.ADDR_AUDIO_SYSTEM,
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 1220542..1285a61 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -26,6 +26,8 @@
import android.annotation.EnforcePermission;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.PermissionManuallyEnforced;
+import android.annotation.RequiresPermission;
import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
import android.bluetooth.BluetoothAdapter;
@@ -35,6 +37,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.graphics.PixelFormat;
import android.graphics.PointF;
import android.hardware.SensorPrivacyManager;
@@ -84,7 +87,6 @@
import android.os.vibrator.StepSegment;
import android.os.vibrator.VibrationEffectSegment;
import android.provider.DeviceConfig;
-import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.IndentingPrintWriter;
@@ -125,7 +127,6 @@
import com.android.server.input.InputManagerInternal.LidSwitchCallback;
import com.android.server.input.debug.FocusEventDebugView;
import com.android.server.input.debug.TouchpadDebugViewController;
-import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.policy.WindowManagerPolicy;
import libcore.io.IoUtils;
@@ -175,7 +176,7 @@
private final InputManagerHandler mHandler;
private DisplayManagerInternal mDisplayManagerInternal;
- private InputMethodManagerInternal mInputMethodManagerInternal;
+ private PackageManagerInternal mPackageManagerInternal;
private final File mDoubleTouchGestureEnableFile;
@@ -546,8 +547,7 @@
}
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
- mInputMethodManagerInternal =
- LocalServices.getService(InputMethodManagerInternal.class);
+ mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
mSettingsObserver.registerAndUpdate();
@@ -597,9 +597,6 @@
mKeyRemapper.systemRunning();
mPointerIconCache.systemRunning();
mKeyboardGlyphManager.systemRunning();
- if (mTouchpadDebugViewController != null) {
- mTouchpadDebugViewController.systemRunning();
- }
}
private void reloadDeviceAliases() {
@@ -2272,13 +2269,15 @@
// Native callback.
@SuppressWarnings("unused")
private void notifyTouchpadHardwareState(TouchpadHardwareState hardwareStates, int deviceId) {
- // TODO(b/286551975): sent the touchpad hardware state data here to TouchpadDebugActivity
Slog.d(TAG, "notifyTouchpadHardwareState: Time: "
+ hardwareStates.getTimestamp() + ", No. Buttons: "
+ hardwareStates.getButtonsDown() + ", No. Fingers: "
+ hardwareStates.getFingerCount() + ", No. Touch: "
+ hardwareStates.getTouchCount() + ", Id: "
+ deviceId);
+ if (mTouchpadDebugViewController != null) {
+ mTouchpadDebugViewController.updateTouchpadHardwareState(hardwareStates);
+ }
}
// Native callback.
@@ -2743,21 +2742,48 @@
lockedModifierState);
}
+ /**
+ * Enforces the caller contains the necessary permission to manage key gestures.
+ */
+ @RequiresPermission(Manifest.permission.MANAGE_KEY_GESTURES)
+ private void enforceManageKeyGesturePermission() {
+ // TODO(b/361567988): Use @EnforcePermission to enforce permission once flag guarding the
+ // permission is rolled out
+ String systemUIPackage = mContext.getString(R.string.config_systemUi);
+ int systemUIAppId = UserHandle.getAppId(mPackageManagerInternal
+ .getPackageUid(systemUIPackage, PackageManager.MATCH_SYSTEM_ONLY,
+ UserHandle.USER_SYSTEM));
+ if (UserHandle.getCallingAppId() == systemUIAppId) {
+ return;
+ }
+ if (mContext.checkCallingOrSelfPermission(
+ Manifest.permission.MANAGE_KEY_GESTURES) == PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+
+ String message = "Managing Key Gestures requires the following permission: "
+ + Manifest.permission.MANAGE_KEY_GESTURES;
+ throw new SecurityException(message);
+ }
+
+
@Override
- @EnforcePermission(Manifest.permission.MANAGE_KEY_GESTURES)
+ @PermissionManuallyEnforced
public void registerKeyGestureEventListener(
@NonNull IKeyGestureEventListener listener) {
- super.registerKeyGestureEventListener_enforcePermission();
+ enforceManageKeyGesturePermission();
+
Objects.requireNonNull(listener);
mKeyGestureController.registerKeyGestureEventListener(listener,
Binder.getCallingPid());
}
@Override
- @EnforcePermission(Manifest.permission.MANAGE_KEY_GESTURES)
+ @PermissionManuallyEnforced
public void unregisterKeyGestureEventListener(
@NonNull IKeyGestureEventListener listener) {
- super.unregisterKeyGestureEventListener_enforcePermission();
+ enforceManageKeyGesturePermission();
+
Objects.requireNonNull(listener);
mKeyGestureController.unregisterKeyGestureEventListener(listener,
Binder.getCallingPid());
@@ -3340,6 +3366,13 @@
}
}
+ void updateTouchpadVisualizerEnabled(boolean enabled) {
+ mNative.setShouldNotifyTouchpadHardwareState(enabled);
+ if (mTouchpadDebugViewController != null) {
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(enabled);
+ }
+ }
+
void updatePointerLocationEnabled(boolean enabled) {
mWindowManagerCallbacks.notifyPointerLocationChanged(enabled);
}
diff --git a/services/core/java/com/android/server/input/InputSettingsObserver.java b/services/core/java/com/android/server/input/InputSettingsObserver.java
index ef61d02..835fb72 100644
--- a/services/core/java/com/android/server/input/InputSettingsObserver.java
+++ b/services/core/java/com/android/server/input/InputSettingsObserver.java
@@ -180,7 +180,7 @@
}
private void updateTouchpadHardwareStateNotificationsEnabled() {
- mNative.setShouldNotifyTouchpadHardwareState(InputSettings.useTouchpadVisualizer(mContext));
+ mService.updateTouchpadVisualizerEnabled(InputSettings.useTouchpadVisualizer(mContext));
}
private void updateTouchpadRightClickZoneEnabled() {
diff --git a/services/core/java/com/android/server/input/debug/TouchpadDebugView.java b/services/core/java/com/android/server/input/debug/TouchpadDebugView.java
index 5fca771..ba56ad0 100644
--- a/services/core/java/com/android/server/input/debug/TouchpadDebugView.java
+++ b/services/core/java/com/android/server/input/debug/TouchpadDebugView.java
@@ -16,45 +16,96 @@
package com.android.server.input.debug;
+import android.annotation.NonNull;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.util.Slog;
import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
-public class TouchpadDebugView extends LinearLayout {
+import com.android.server.input.TouchpadFingerState;
+import com.android.server.input.TouchpadHardwareState;
+import java.util.Objects;
+
+public class TouchpadDebugView extends LinearLayout {
/**
* Input device ID for the touchpad that this debug view is displaying.
*/
private final int mTouchpadId;
+ @NonNull
+ private final WindowManager mWindowManager;
+
+ @NonNull
+ private final WindowManager.LayoutParams mWindowLayoutParams;
+
+ private final int mTouchSlop;
+
+ private float mTouchDownX;
+ private float mTouchDownY;
+ private int mScreenWidth;
+ private int mScreenHeight;
+ private int mWindowLocationBeforeDragX;
+ private int mWindowLocationBeforeDragY;
+ @NonNull
+ private TouchpadHardwareState mLastTouchpadState =
+ new TouchpadHardwareState(0, 0 /* buttonsDown */, 0, 0,
+ new TouchpadFingerState[0]);
+
public TouchpadDebugView(Context context, int touchpadId) {
super(context);
mTouchpadId = touchpadId;
+ mWindowManager =
+ Objects.requireNonNull(getContext().getSystemService(WindowManager.class));
init(context);
+ mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+
+ // TODO(b/360137366): Use the hardware properties to initialise layout parameters.
+ mWindowLayoutParams = new WindowManager.LayoutParams();
+ mWindowLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+ mWindowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+ mWindowLayoutParams.privateFlags |=
+ WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
+ mWindowLayoutParams.setFitInsetsTypes(0);
+ mWindowLayoutParams.layoutInDisplayCutoutMode =
+ WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ mWindowLayoutParams.format = PixelFormat.TRANSLUCENT;
+ mWindowLayoutParams.setTitle("TouchpadDebugView - display " + mContext.getDisplayId());
+
+ mWindowLayoutParams.x = 40;
+ mWindowLayoutParams.y = 100;
+ mWindowLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
+ mWindowLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
+ mWindowLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;
}
private void init(Context context) {
setOrientation(VERTICAL);
- setLayoutParams(new LinearLayout.LayoutParams(
- LinearLayout.LayoutParams.WRAP_CONTENT,
- LinearLayout.LayoutParams.WRAP_CONTENT));
- setBackgroundColor(Color.TRANSPARENT);
+ setLayoutParams(new LayoutParams(
+ LayoutParams.WRAP_CONTENT,
+ LayoutParams.WRAP_CONTENT));
+ setBackgroundColor(Color.RED);
// TODO(b/286551975): Replace this content with the touchpad debug view.
-
TextView textView1 = new TextView(context);
- textView1.setBackgroundColor(Color.parseColor("#FFFF0000"));
+ textView1.setBackgroundColor(Color.TRANSPARENT);
textView1.setTextSize(20);
textView1.setText("Touchpad Debug View 1");
textView1.setGravity(Gravity.CENTER);
textView1.setTextColor(Color.WHITE);
-
textView1.setLayoutParams(new LayoutParams(1000, 200));
TextView textView2 = new TextView(context);
- textView2.setBackgroundColor(Color.BLUE);
+ textView2.setBackgroundColor(Color.TRANSPARENT);
textView2.setTextSize(20);
textView2.setText("Touchpad Debug View 2");
textView2.setGravity(Gravity.CENTER);
@@ -63,9 +114,123 @@
addView(textView1);
addView(textView2);
+
+ updateScreenDimensions();
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ float deltaX;
+ float deltaY;
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mWindowLocationBeforeDragX = mWindowLayoutParams.x;
+ mWindowLocationBeforeDragY = mWindowLayoutParams.y;
+ mTouchDownX = event.getRawX() - mWindowLocationBeforeDragX;
+ mTouchDownY = event.getRawY() - mWindowLocationBeforeDragY;
+ return true;
+
+ case MotionEvent.ACTION_MOVE:
+ deltaX = event.getRawX() - mWindowLayoutParams.x - mTouchDownX;
+ deltaY = event.getRawY() - mWindowLayoutParams.y - mTouchDownY;
+ if (isSlopExceeded(deltaX, deltaY)) {
+ mWindowLayoutParams.x =
+ Math.max(0, Math.min((int) (event.getRawX() - mTouchDownX),
+ mScreenWidth - this.getWidth()));
+ mWindowLayoutParams.y =
+ Math.max(0, Math.min((int) (event.getRawY() - mTouchDownY),
+ mScreenHeight - this.getHeight()));
+
+ mWindowManager.updateViewLayout(this, mWindowLayoutParams);
+ }
+ return true;
+
+ case MotionEvent.ACTION_UP:
+ deltaX = event.getRawX() - mWindowLayoutParams.x - mTouchDownX;
+ deltaY = event.getRawY() - mWindowLayoutParams.y - mTouchDownY;
+ if (!isSlopExceeded(deltaX, deltaY)) {
+ performClick();
+ }
+ return true;
+
+ case MotionEvent.ACTION_CANCEL:
+ // Move the window back to the original position
+ mWindowLayoutParams.x = mWindowLocationBeforeDragX;
+ mWindowLayoutParams.y = mWindowLocationBeforeDragY;
+ mWindowManager.updateViewLayout(this, mWindowLayoutParams);
+ return true;
+
+ default:
+ return super.onTouchEvent(event);
+ }
+ }
+
+ @Override
+ public boolean performClick() {
+ super.performClick();
+ Slog.d("TouchpadDebugView", "You tapped the window!");
+ return true;
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ updateScreenDimensions();
+
+ // Adjust view position to stay within screen bounds after rotation
+ mWindowLayoutParams.x =
+ Math.max(0, Math.min(mWindowLayoutParams.x, mScreenWidth - getWidth()));
+ mWindowLayoutParams.y =
+ Math.max(0, Math.min(mWindowLayoutParams.y, mScreenHeight - getHeight()));
+ mWindowManager.updateViewLayout(this, mWindowLayoutParams);
+ }
+
+ private boolean isSlopExceeded(float deltaX, float deltaY) {
+ return deltaX * deltaX + deltaY * deltaY >= mTouchSlop * mTouchSlop;
+ }
+
+ private void updateScreenDimensions() {
+ Rect windowBounds =
+ mWindowManager.getCurrentWindowMetrics().getBounds();
+ mScreenWidth = windowBounds.width();
+ mScreenHeight = windowBounds.height();
}
public int getTouchpadId() {
return mTouchpadId;
}
+
+ public WindowManager.LayoutParams getWindowLayoutParams() {
+ return mWindowLayoutParams;
+ }
+
+ public void updateHardwareState(TouchpadHardwareState touchpadHardwareState) {
+ if (mLastTouchpadState.getButtonsDown() == 0) {
+ if (touchpadHardwareState.getButtonsDown() > 0) {
+ onTouchpadButtonPress();
+ }
+ } else {
+ if (touchpadHardwareState.getButtonsDown() == 0) {
+ onTouchpadButtonRelease();
+ }
+ }
+ mLastTouchpadState = touchpadHardwareState;
+ }
+
+ private void onTouchpadButtonPress() {
+ Slog.d("TouchpadDebugView", "You clicked me!");
+
+ // Iterate through all child views
+ // Temporary demonstration for testing
+ for (int i = 0; i < getChildCount(); i++) {
+ getChildAt(i).setBackgroundColor(Color.BLUE);
+ }
+ }
+
+ private void onTouchpadButtonRelease() {
+ Slog.d("TouchpadDebugView", "You released the click");
+ for (int i = 0; i < getChildCount(); i++) {
+ getChildAt(i).setBackgroundColor(Color.RED);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java b/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java
index c7760c6..bc53c49 100644
--- a/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java
+++ b/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java
@@ -18,74 +18,85 @@
import android.annotation.Nullable;
import android.content.Context;
-import android.graphics.PixelFormat;
-import android.hardware.display.DisplayManager;
import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.Looper;
import android.util.Slog;
-import android.view.Display;
-import android.view.Gravity;
import android.view.InputDevice;
import android.view.WindowManager;
import com.android.server.input.InputManagerService;
import com.android.server.input.TouchpadHardwareProperties;
+import com.android.server.input.TouchpadHardwareState;
import java.util.Objects;
-public class TouchpadDebugViewController {
+public class TouchpadDebugViewController implements InputManager.InputDeviceListener {
- private static final String TAG = "TouchpadDebugViewController";
+ private static final String TAG = "TouchpadDebugView";
private final Context mContext;
private final Handler mHandler;
+
@Nullable
private TouchpadDebugView mTouchpadDebugView;
+
private final InputManagerService mInputManagerService;
+ private boolean mTouchpadVisualizerEnabled = false;
public TouchpadDebugViewController(Context context, Looper looper,
- InputManagerService inputManagerService) {
- final DisplayManager displayManager = Objects.requireNonNull(
- context.getSystemService(DisplayManager.class));
- final Display defaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
- mContext = context.createDisplayContext(defaultDisplay);
+ InputManagerService inputManagerService) {
+ //TODO(b/363979581): Handle multi-display scenarios
+ mContext = context;
mHandler = new Handler(looper);
mInputManagerService = inputManagerService;
}
- public void systemRunning() {
+ @Override
+ public void onInputDeviceAdded(int deviceId) {
final InputManager inputManager = Objects.requireNonNull(
mContext.getSystemService(InputManager.class));
- inputManager.registerInputDeviceListener(mInputDeviceListener, mHandler);
- for (int deviceId : inputManager.getInputDeviceIds()) {
- mInputDeviceListener.onInputDeviceAdded(deviceId);
+ InputDevice inputDevice = inputManager.getInputDevice(deviceId);
+
+ if (Objects.requireNonNull(inputDevice).supportsSource(
+ InputDevice.SOURCE_TOUCHPAD | InputDevice.SOURCE_MOUSE)
+ && mTouchpadVisualizerEnabled) {
+ showDebugView(deviceId);
}
}
- private final InputManager.InputDeviceListener mInputDeviceListener =
- new InputManager.InputDeviceListener() {
- @Override
- public void onInputDeviceAdded(int deviceId) {
- final InputManager inputManager = Objects.requireNonNull(
- mContext.getSystemService(InputManager.class));
- InputDevice inputDevice = inputManager.getInputDevice(deviceId);
+ @Override
+ public void onInputDeviceRemoved(int deviceId) {
+ hideDebugView(deviceId);
+ }
- if (Objects.requireNonNull(inputDevice).supportsSource(
- InputDevice.SOURCE_TOUCHPAD | InputDevice.SOURCE_MOUSE)) {
- showDebugView(deviceId);
- }
- }
+ @Override
+ public void onInputDeviceChanged(int deviceId) {
+ }
- @Override
- public void onInputDeviceRemoved(int deviceId) {
- hideDebugView(deviceId);
- }
-
- @Override
- public void onInputDeviceChanged(int deviceId) {
- }
- };
+ /**
+ * Notify the controller that the touchpad visualizer setting value has changed.
+ * This must be called from the same looper thread as {@code mHandler}.
+ */
+ public void updateTouchpadVisualizerEnabled(boolean touchpadVisualizerEnabled) {
+ if (mTouchpadVisualizerEnabled == touchpadVisualizerEnabled) {
+ return;
+ }
+ mTouchpadVisualizerEnabled = touchpadVisualizerEnabled;
+ final InputManager inputManager = Objects.requireNonNull(
+ mContext.getSystemService(InputManager.class));
+ if (touchpadVisualizerEnabled) {
+ inputManager.registerInputDeviceListener(this, mHandler);
+ for (int deviceId : inputManager.getInputDeviceIds()) {
+ onInputDeviceAdded(deviceId);
+ }
+ } else {
+ if (mTouchpadDebugView != null) {
+ hideDebugView(mTouchpadDebugView.getTouchpadId());
+ }
+ inputManager.unregisterInputDeviceListener(this);
+ }
+ }
private void showDebugView(int touchpadId) {
if (mTouchpadDebugView != null) {
@@ -95,32 +106,15 @@
mContext.getSystemService(WindowManager.class));
mTouchpadDebugView = new TouchpadDebugView(mContext, touchpadId);
+ final WindowManager.LayoutParams mWindowLayoutParams =
+ mTouchpadDebugView.getWindowLayoutParams();
- final WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
- lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
- lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
- lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
- lp.setFitInsetsTypes(0);
- lp.layoutInDisplayCutoutMode =
- WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
- lp.format = PixelFormat.TRANSLUCENT;
- lp.setTitle("TouchpadDebugView - display " + mContext.getDisplayId());
- lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
-
- lp.x = 40;
- lp.y = 100;
- lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
- lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
- lp.gravity = Gravity.TOP | Gravity.LEFT;
-
- wm.addView(mTouchpadDebugView, lp);
+ wm.addView(mTouchpadDebugView, mWindowLayoutParams);
Slog.d(TAG, "Touchpad debug view created.");
TouchpadHardwareProperties mTouchpadHardwareProperties =
mInputManagerService.getTouchpadHardwareProperties(
touchpadId);
- // TODO(b/360137366): Use the hardware properties to initialise layout parameters.
if (mTouchpadHardwareProperties != null) {
Slog.d(TAG, mTouchpadHardwareProperties.toString());
} else {
@@ -139,4 +133,10 @@
mTouchpadDebugView = null;
Slog.d(TAG, "Touchpad debug view removed.");
}
+
+ public void updateTouchpadHardwareState(TouchpadHardwareState touchpadHardwareState) {
+ if (mTouchpadDebugView != null) {
+ mTouchpadDebugView.updateHardwareState(touchpadHardwareState);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 7cfd2cc..f747879 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -350,13 +350,15 @@
@BinderThread
private int resolveImeUserIdLocked(@UserIdInt int callingProcessUserId,
@NonNull IInputMethodClient client) {
- if (mConcurrentMultiUserModeEnabled
- && callingProcessUserId == UserHandle.USER_SYSTEM) {
- final var clientState = mClientController.getClient(client.asBinder());
- return mUserManagerInternal.getUserAssignedToDisplay(
- clientState.mSelfReportedDisplayId);
+ if (mConcurrentMultiUserModeEnabled) {
+ if (callingProcessUserId == UserHandle.USER_SYSTEM) {
+ final var clientState = mClientController.getClient(client.asBinder());
+ return mUserManagerInternal.getUserAssignedToDisplay(
+ clientState.mSelfReportedDisplayId);
+ }
+ return callingProcessUserId;
}
- return callingProcessUserId;
+ return mCurrentImeUserId;
}
/**
@@ -4676,6 +4678,7 @@
}
}
+ // TODO(b/356239178): Make dump proto multi-user aware.
private void dumpDebug(ProtoOutputStream proto, long fieldId) {
synchronized (ImfLock.class) {
final int userId = mCurrentImeUserId;
@@ -6101,17 +6104,40 @@
@BinderThread
private void dumpAsStringNoCheck(FileDescriptor fd, PrintWriter pw, String[] args,
boolean isCritical) {
+ final int argUserId = parseUserIdFromDumpArgs(args);
+ final Printer p = new PrintWriterPrinter(pw);
+ p.println("Current Input Method Manager state:");
+ p.println(" concurrentMultiUserModeEnabled=" + mConcurrentMultiUserModeEnabled);
+ if (mConcurrentMultiUserModeEnabled && argUserId == UserHandle.USER_NULL) {
+ mUserDataRepository.forAllUserData(
+ u -> dumpAsStringNoCheckForUser(u, fd, pw, args, isCritical));
+ } else {
+ final int userId = argUserId != UserHandle.USER_NULL ? argUserId : mCurrentImeUserId;
+ final var userData = getUserData(userId);
+ dumpAsStringNoCheckForUser(userData, fd, pw, args, isCritical);
+ }
+ }
+
+ @UserIdInt
+ private static int parseUserIdFromDumpArgs(String[] args) {
+ final int userIdx = Arrays.binarySearch(args, "--user");
+ if (userIdx == -1 || userIdx == args.length - 1) {
+ return UserHandle.USER_NULL;
+ }
+ return Integer.parseInt(args[userIdx + 1]);
+ }
+
+ // TODO(b/356239178): Update dump format output to better group per-user info.
+ @BinderThread
+ private void dumpAsStringNoCheckForUser(UserData userData, FileDescriptor fd, PrintWriter pw,
+ String[] args, boolean isCritical) {
+ final Printer p = new PrintWriterPrinter(pw);
IInputMethodInvoker method;
ClientState client;
-
- final Printer p = new PrintWriterPrinter(pw);
-
+ p.println(" UserId=" + userData.mUserId);
synchronized (ImfLock.class) {
- final int userId = mCurrentImeUserId;
- final InputMethodSettings settings = InputMethodSettingsRepository.get(userId);
- final var userData = getUserData(userId);
- p.println("Current Input Method Manager state:");
- p.println(" concurrentMultiUserModeEnabled" + mConcurrentMultiUserModeEnabled);
+ final InputMethodSettings settings = InputMethodSettingsRepository.get(
+ userData.mUserId);
final List<InputMethodInfo> methodList = settings.getMethodList();
int numImes = methodList.size();
p.println(" Input Methods:");
@@ -6131,7 +6157,7 @@
p.println(" sessionRequested="
+ c.mSessionRequested);
p.println(" sessionRequestedForAccessibility="
- + c.mSessionRequestedForAccessibility);
+ + c.mSessionRequestedForAccessibility);
p.println(" curSession=" + c.mCurSession);
p.println(" selfReportedDisplayId=" + c.mSelfReportedDisplayId);
p.println(" uid=" + c.mUid);
@@ -6139,7 +6165,6 @@
};
mClientController.forAllClients(clientControllerDump);
final var bindingController = userData.mBindingController;
- p.println(" mCurrentImeUserId=" + userData.mUserId);
p.println(" mCurMethodId=" + bindingController.getSelectedMethodId());
client = userData.mCurClient;
p.println(" mCurClient=" + client + " mCurSeq="
@@ -6232,8 +6257,6 @@
p.println("No input method client.");
}
synchronized (ImfLock.class) {
- final int userId = mCurrentImeUserId;
- final var userData = getUserData(userId);
if (userData.mImeBindingState.mFocusedWindowClient != null
&& client != userData.mImeBindingState.mFocusedWindowClient) {
p.println(" ");
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index db4d68b..38ef5b8 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -756,15 +756,9 @@
unlockIntent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- PendingIntent intent;
- if (android.app.admin.flags.Flags.hsumUnlockNotificationFix()) {
- intent = PendingIntent.getActivityAsUser(mContext, 0, unlockIntent,
- PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED,
- null, parent);
- } else {
- intent = PendingIntent.getActivity(mContext, 0, unlockIntent,
- PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
- }
+ PendingIntent intent = PendingIntent.getActivityAsUser(mContext, 0, unlockIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED,
+ null, parent);
Slogf.d(TAG, "Showing encryption notification for user %d; reason: %s",
user.getIdentifier(), reason);
@@ -3409,8 +3403,13 @@
// It's OK to dump the credential type since anyone with physical access can just
// observe it from the keyguard directly.
pw.println("Quality: " + getKeyguardStoredQuality(userId));
- pw.println("CredentialType: " + LockPatternUtils.credentialTypeToString(
- getCredentialTypeInternal(userId)));
+ final int credentialType = getCredentialTypeInternal(userId);
+ pw.println("CredentialType: "
+ + LockPatternUtils.credentialTypeToString(credentialType));
+ if (credentialType == CREDENTIAL_TYPE_NONE) {
+ pw.println("IsLockScreenDisabled: "
+ + getBoolean(LockPatternUtils.DISABLE_LOCKSCREEN_KEY, false, userId));
+ }
pw.println("SeparateChallenge: " + getSeparateProfileChallengeEnabledInternal(userId));
pw.println(TextUtils.formatSimple("Metrics: %s",
getUserPasswordMetrics(userId) != null ? "known" : "unknown"));
diff --git a/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java b/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
index c8cb54f..925ba17 100644
--- a/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
+++ b/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
@@ -19,6 +19,10 @@
import static android.app.UiModeManager.MODE_ATTENTION_THEME_OVERLAY_NIGHT;
import static android.app.UiModeManager.MODE_ATTENTION_THEME_OVERLAY_OFF;
+import static com.android.server.notification.ZenLog.traceApplyDeviceEffect;
+import static com.android.server.notification.ZenLog.traceScheduleApplyDeviceEffect;
+
+import android.app.KeyguardManager;
import android.app.UiModeManager;
import android.app.WallpaperManager;
import android.content.BroadcastReceiver;
@@ -50,6 +54,7 @@
private final Context mContext;
private final ColorDisplayManager mColorDisplayManager;
+ private final KeyguardManager mKeyguardManager;
private final PowerManager mPowerManager;
private final UiModeManager mUiModeManager;
private final WallpaperManager mWallpaperManager;
@@ -64,6 +69,7 @@
DefaultDeviceEffectsApplier(Context context) {
mContext = context;
mColorDisplayManager = context.getSystemService(ColorDisplayManager.class);
+ mKeyguardManager = context.getSystemService(KeyguardManager.class);
mPowerManager = context.getSystemService(PowerManager.class);
mUiModeManager = context.getSystemService(UiModeManager.class);
WallpaperManager wallpaperManager = context.getSystemService(WallpaperManager.class);
@@ -77,6 +83,8 @@
if (mLastAppliedEffects.shouldSuppressAmbientDisplay()
!= effects.shouldSuppressAmbientDisplay()) {
try {
+ traceApplyDeviceEffect("suppressAmbientDisplay",
+ effects.shouldSuppressAmbientDisplay());
mPowerManager.suppressAmbientDisplay(SUPPRESS_AMBIENT_DISPLAY_TOKEN,
effects.shouldSuppressAmbientDisplay());
} catch (Exception e) {
@@ -87,6 +95,8 @@
if (mLastAppliedEffects.shouldDisplayGrayscale() != effects.shouldDisplayGrayscale()) {
if (mColorDisplayManager != null) {
try {
+ traceApplyDeviceEffect("displayGrayscale",
+ effects.shouldDisplayGrayscale());
mColorDisplayManager.setSaturationLevel(
effects.shouldDisplayGrayscale() ? SATURATION_LEVEL_GRAYSCALE
: SATURATION_LEVEL_FULL_COLOR);
@@ -99,6 +109,7 @@
if (mLastAppliedEffects.shouldDimWallpaper() != effects.shouldDimWallpaper()) {
if (mWallpaperManager != null) {
try {
+ traceApplyDeviceEffect("dimWallpaper", effects.shouldDimWallpaper());
mWallpaperManager.setWallpaperDimAmount(
effects.shouldDimWallpaper() ? WALLPAPER_DIM_AMOUNT_DIMMED
: WALLPAPER_DIM_AMOUNT_NORMAL);
@@ -125,15 +136,18 @@
// Changing the theme can be disruptive for the user (Activities are likely recreated, may
// lose some state). Therefore we only apply the change immediately if the rule was
- // activated manually, or we are initializing, or the screen is currently off/dreaming.
+ // activated manually, or we are initializing, or the screen is currently off/dreaming,
+ // or if the device is locked.
if (origin == ZenModeConfig.ORIGIN_INIT
|| origin == ZenModeConfig.ORIGIN_INIT_USER
|| origin == ZenModeConfig.ORIGIN_USER_IN_SYSTEMUI
|| origin == ZenModeConfig.ORIGIN_USER_IN_APP
- || !mPowerManager.isInteractive()) {
+ || !mPowerManager.isInteractive()
+ || (android.app.Flags.modesUi() && mKeyguardManager.isKeyguardLocked())) {
unregisterScreenOffReceiver();
updateNightModeImmediately(useNightMode);
} else {
+ traceScheduleApplyDeviceEffect("nightMode", useNightMode);
registerScreenOffReceiver();
}
}
@@ -150,6 +164,7 @@
private void updateNightModeImmediately(boolean useNightMode) {
Binder.withCleanCallingIdentity(() -> {
try {
+ traceApplyDeviceEffect("nightMode", useNightMode);
mUiModeManager.setAttentionModeThemeOverlay(
useNightMode ? MODE_ATTENTION_THEME_OVERLAY_NIGHT
: MODE_ATTENTION_THEME_OVERLAY_OFF);
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 1fdb57c..3523a33 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -75,7 +75,9 @@
import com.android.internal.util.function.TriPredicate;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
+import com.android.server.LocalServices;
import com.android.server.notification.NotificationManagerService.DumpFilter;
+import com.android.server.pm.UserManagerInternal;
import com.android.server.utils.TimingsTraceAndSlog;
import org.xmlpull.v1.XmlPullParser;
@@ -101,7 +103,7 @@
* - A remote interface definition (aidl) provided by the service used for communication.
*/
abstract public class ManagedServices {
- protected final String TAG = getClass().getSimpleName();
+ protected final String TAG = getClass().getSimpleName().replace('$', '.');
protected final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final int ON_BINDING_DIED_REBIND_DELAY_MS = 10000;
@@ -134,6 +136,7 @@
private final UserProfiles mUserProfiles;
protected final IPackageManager mPm;
protected final UserManager mUm;
+ private final UserManagerInternal mUserManagerInternal;
private final Config mConfig;
private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -195,6 +198,7 @@
mConfig = getConfig();
mApprovalLevel = APPROVAL_BY_COMPONENT;
mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
}
abstract protected Config getConfig();
@@ -950,7 +954,7 @@
|| isPackageOrComponentAllowed(component.getPackageName(), userId))) {
return false;
}
- return isValidService(component, userId);
+ return componentHasBindPermission(component, userId);
}
private boolean componentHasBindPermission(ComponentName component, int userId) {
@@ -1302,12 +1306,11 @@
if (TextUtils.equals(getPackageName(approvedPackageOrComponent), packageName)) {
final ComponentName component = ComponentName.unflattenFromString(
approvedPackageOrComponent);
- if (component != null && !isValidService(component, userId)) {
+ if (component != null && !componentHasBindPermission(component, userId)) {
approved.removeAt(j);
if (DEBUG) {
Slog.v(TAG, "Removing " + approvedPackageOrComponent
- + " from approved list; no bind permission or "
- + "service interface filter found "
+ + " from approved list; no bind permission found "
+ mConfig.bindPermission);
}
}
@@ -1326,11 +1329,6 @@
}
}
- protected boolean isValidService(ComponentName component, int userId) {
- return componentHasBindPermission(component, userId) && queryPackageForServices(
- component.getPackageName(), userId).contains(component);
- }
-
protected boolean isValidEntry(String packageOrComponent, int userId) {
return hasMatchingServices(packageOrComponent, userId);
}
@@ -1372,9 +1370,14 @@
@GuardedBy("mMutex")
protected void populateComponentsToBind(SparseArray<Set<ComponentName>> componentsToBind,
final IntArray activeUsers,
- SparseArray<ArraySet<ComponentName>> approvedComponentsByUser) {
- mEnabledServicesForCurrentProfiles.clear();
- mEnabledServicesPackageNames.clear();
+ SparseArray<ArraySet<ComponentName>> approvedComponentsByUser,
+ boolean isVisibleBackgroundUser) {
+ // When it is a visible background user in Automotive MUMD environment,
+ // don't clear mEnabledServicesForCurrentProfile and mEnabledServicesPackageNames.
+ if (!isVisibleBackgroundUser) {
+ mEnabledServicesForCurrentProfiles.clear();
+ mEnabledServicesPackageNames.clear();
+ }
final int nUserIds = activeUsers.size();
for (int i = 0; i < nUserIds; ++i) {
@@ -1395,7 +1398,12 @@
}
componentsToBind.put(userId, add);
-
+ // When it is a visible background user in Automotive MUMD environment,
+ // skip adding items to mEnabledServicesForCurrentProfile
+ // and mEnabledServicesPackageNames.
+ if (isVisibleBackgroundUser) {
+ continue;
+ }
mEnabledServicesForCurrentProfiles.addAll(userComponents);
for (int j = 0; j < userComponents.size(); j++) {
@@ -1443,7 +1451,10 @@
IntArray userIds = mUserProfiles.getCurrentProfileIds();
boolean rebindAllCurrentUsers = mUserProfiles.isProfileUser(userToRebind, mContext)
&& allowRebindForParentUser();
+ boolean isVisibleBackgroundUser = false;
if (userToRebind != USER_ALL && !rebindAllCurrentUsers) {
+ isVisibleBackgroundUser =
+ mUserManagerInternal.isVisibleBackgroundFullUser(userToRebind);
userIds = new IntArray(1);
userIds.add(userToRebind);
}
@@ -1458,7 +1469,8 @@
// Filter approvedComponentsByUser to collect all of the components that are allowed
// for the currently active user(s).
- populateComponentsToBind(componentsToBind, userIds, approvedComponentsByUser);
+ populateComponentsToBind(componentsToBind, userIds, approvedComponentsByUser,
+ isVisibleBackgroundUser);
// For every current non-system connection, disconnect services that are no longer
// approved, or ALL services if we are force rebinding
diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java
index 82c5733..1aa5ac0 100644
--- a/services/core/java/com/android/server/notification/ZenLog.java
+++ b/services/core/java/com/android/server/notification/ZenLog.java
@@ -23,18 +23,15 @@
import android.os.Build;
import android.os.RemoteException;
import android.provider.Settings.Global;
-import android.service.notification.Condition;
import android.service.notification.IConditionProvider;
import android.service.notification.NotificationListenerService;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeDiff;
import android.util.LocalLog;
-import android.util.Log;
-import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
-import java.text.SimpleDateFormat;
-import java.util.Date;
import java.util.List;
public class ZenLog {
@@ -61,6 +58,8 @@
private static final int TYPE_RECORD_CALLER = 19;
private static final int TYPE_CHECK_REPEAT_CALLER = 20;
private static final int TYPE_ALERT_ON_UPDATED_INTERCEPT = 21;
+ private static final int TYPE_APPLY_DEVICE_EFFECT = 22;
+ private static final int TYPE_SCHEDULE_APPLY_DEVICE_EFFECT = 23;
public static void traceIntercepted(NotificationRecord record, String reason) {
append(TYPE_INTERCEPTED, record.getKey() + "," + reason);
@@ -173,6 +172,14 @@
+ ", given uri=" + hasUri);
}
+ public static void traceApplyDeviceEffect(String effect, boolean newValue) {
+ append(TYPE_APPLY_DEVICE_EFFECT, effect + " -> " + newValue);
+ }
+
+ public static void traceScheduleApplyDeviceEffect(String effect, boolean scheduledValue) {
+ append(TYPE_SCHEDULE_APPLY_DEVICE_EFFECT, effect + " -> " + scheduledValue);
+ }
+
private static String subscribeResult(IConditionProvider provider, RemoteException e) {
return provider == null ? "no provider" : e != null ? e.getMessage() : "ok";
}
@@ -196,6 +203,8 @@
case TYPE_RECORD_CALLER: return "record_caller";
case TYPE_CHECK_REPEAT_CALLER: return "check_repeat_caller";
case TYPE_ALERT_ON_UPDATED_INTERCEPT: return "alert_on_updated_intercept";
+ case TYPE_APPLY_DEVICE_EFFECT: return "apply_device_effect";
+ case TYPE_SCHEDULE_APPLY_DEVICE_EFFECT: return "schedule_device_effect";
default: return "unknown";
}
}
@@ -273,4 +282,14 @@
STATE_CHANGES.dump(prefix, pw);
}
}
+
+ @VisibleForTesting(/* otherwise = VisibleForTesting.NONE */)
+ public static void clear() {
+ synchronized (INTERCEPTION_EVENTS) {
+ INTERCEPTION_EVENTS.clear();
+ }
+ synchronized (STATE_CHANGES) {
+ STATE_CHANGES.clear();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 333b3e2..2ada9ae4 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -2125,17 +2125,25 @@
@GuardedBy("mConfigLock")
private void applyCustomPolicy(ZenPolicy policy, ZenRule rule, boolean useManualConfig) {
if (rule.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
- policy.apply(new ZenPolicy.Builder()
- .disallowAllSounds()
- .allowPriorityChannels(false)
- .build());
+ if (Flags.modesApi() && Flags.modesUi()) {
+ policy.apply(ZenPolicy.getBasePolicyInterruptionFilterNone());
+ } else {
+ policy.apply(new ZenPolicy.Builder()
+ .disallowAllSounds()
+ .allowPriorityChannels(false)
+ .build());
+ }
} else if (rule.zenMode == Global.ZEN_MODE_ALARMS) {
- policy.apply(new ZenPolicy.Builder()
- .disallowAllSounds()
- .allowAlarms(true)
- .allowMedia(true)
- .allowPriorityChannels(false)
- .build());
+ if (Flags.modesApi() && Flags.modesUi()) {
+ policy.apply(ZenPolicy.getBasePolicyInterruptionFilterAlarms());
+ } else {
+ policy.apply(new ZenPolicy.Builder()
+ .disallowAllSounds()
+ .allowAlarms(true)
+ .allowMedia(true)
+ .allowPriorityChannels(false)
+ .build());
+ }
} else if (rule.zenPolicy != null) {
policy.apply(rule.zenPolicy);
} else {
diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java
index e34bdc6..9ecc7b9 100644
--- a/services/core/java/com/android/server/pm/DexOptHelper.java
+++ b/services/core/java/com/android/server/pm/DexOptHelper.java
@@ -19,6 +19,7 @@
import static android.content.pm.PackageManager.INSTALL_REASON_DEVICE_RESTORE;
import static android.content.pm.PackageManager.INSTALL_REASON_DEVICE_SETUP;
import static android.os.Trace.TRACE_TAG_DALVIK;
+import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.os.incremental.IncrementalManager.isIncrementalPath;
import static com.android.server.LocalManagerRegistry.ManagerNotFoundException;
@@ -739,6 +740,78 @@
}
/**
+ * Perform dexopt if needed for the installation
+ */
+ static void performDexoptIfNeeded(InstallRequest installRequest, DexManager dexManager,
+ Context context, PackageManagerTracedLock.RawLock installLock) {
+
+ // Construct the DexoptOptions early to see if we should skip running dexopt.
+ //
+ // Do not run PackageDexOptimizer through the local performDexOpt
+ // method because `pkg` may not be in `mPackages` yet.
+ //
+ // Also, don't fail application installs if the dexopt step fails.
+ DexoptOptions dexoptOptions = getDexoptOptionsByInstallRequest(installRequest, dexManager);
+ // Check whether we need to dexopt the app.
+ //
+ // NOTE: it is IMPORTANT to call dexopt:
+ // - after doRename which will sync the package data from AndroidPackage and
+ // its corresponding ApplicationInfo.
+ // - after installNewPackageLIF or replacePackageLIF which will update result with the
+ // uid of the application (pkg.applicationInfo.uid).
+ // This update happens in place!
+ //
+ // We only need to dexopt if the package meets ALL of the following conditions:
+ // 1) it is not an instant app or if it is then dexopt is enabled via gservices.
+ // 2) it is not debuggable.
+ // 3) it is not on Incremental File System.
+ //
+ // Note that we do not dexopt instant apps by default. dexopt can take some time to
+ // complete, so we skip this step during installation. Instead, we'll take extra time
+ // the first time the instant app starts. It's preferred to do it this way to provide
+ // continuous progress to the useur instead of mysteriously blocking somewhere in the
+ // middle of running an instant app. The default behaviour can be overridden
+ // via gservices.
+ //
+ // Furthermore, dexopt may be skipped, depending on the install scenario and current
+ // state of the device.
+ //
+ // TODO(b/174695087): instantApp and onIncremental should be removed and their install
+ // path moved to SCENARIO_FAST.
+
+ final boolean performDexopt = DexOptHelper.shouldPerformDexopt(installRequest,
+ dexoptOptions, context);
+ if (performDexopt) {
+ // dexopt can take long, and ArtService doesn't require installd, so we release
+ // the lock here and re-acquire the lock after dexopt is finished.
+ if (installLock != null) {
+ installLock.unlock();
+ }
+ try {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
+
+ // This mirrors logic from commitReconciledScanResultLocked, where the library
+ // files needed for dexopt are assigned.
+ PackageSetting realPkgSetting = installRequest.getRealPackageSetting();
+ // Unfortunately, the updated system app flag is only tracked on this
+ // PackageSetting
+ boolean isUpdatedSystemApp =
+ installRequest.getScannedPackageSetting().isUpdatedSystemApp();
+ realPkgSetting.getPkgState().setUpdatedSystemApp(isUpdatedSystemApp);
+
+ DexoptResult dexOptResult = DexOptHelper.dexoptPackageUsingArtService(
+ installRequest, dexoptOptions);
+ installRequest.onDexoptFinished(dexOptResult);
+ } finally {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (installLock != null) {
+ installLock.lock();
+ }
+ }
+ }
+ }
+
+ /**
* Use ArtService to perform dexopt by the given InstallRequest.
*/
static DexoptResult dexoptPackageUsingArtService(InstallRequest installRequest,
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 1317866..2856eb4 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -172,11 +172,9 @@
import com.android.internal.util.CollectionUtils;
import com.android.server.EventLogTags;
import com.android.server.SystemConfig;
-import com.android.server.art.model.DexoptResult;
import com.android.server.criticalevents.CriticalEventLog;
import com.android.server.pm.dex.ArtManagerService;
import com.android.server.pm.dex.DexManager;
-import com.android.server.pm.dex.DexoptOptions;
import com.android.server.pm.parsing.PackageCacher;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.permission.Permission;
@@ -209,6 +207,7 @@
import java.util.Set;
import java.util.concurrent.ExecutorService;
+
final class InstallPackageHelper {
private final PackageManagerService mPm;
private final AppDataHelper mAppDataHelper;
@@ -989,15 +988,6 @@
return false;
}
- void installPackagesTraced(List<InstallRequest> requests) {
- try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
- installPackagesLI(requests);
- } finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- }
- }
-
/**
* Installs one or more packages atomically. This operation is broken up into four phases:
* <ul>
@@ -1017,36 +1007,89 @@
*
* Failure at any phase will result in a full failure to install all packages.
*/
- @GuardedBy("mPm.mInstallLock")
- private void installPackagesLI(List<InstallRequest> requests) {
- final Set<String> scannedPackages = new ArraySet<>(requests.size());
- final Map<String, Settings.VersionInfo> versionInfos = new ArrayMap<>(requests.size());
- final Map<String, Boolean> createdAppId = new ArrayMap<>(requests.size());
- CriticalEventLog.getInstance().logInstallPackagesStarted();
+ void installPackagesTraced(List<InstallRequest> requests) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
boolean success = false;
+ final Map<String, Boolean> createdAppId = new ArrayMap<>(requests.size());
+ final Map<String, Settings.VersionInfo> versionInfos = new ArrayMap<>(requests.size());
try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI");
+ CriticalEventLog.getInstance().logInstallPackagesStarted();
+
+ if (prepareInstallPackages(requests)
+ && scanInstallPackages(requests, createdAppId, versionInfos)) {
+ List<ReconciledPackage> reconciledPackages =
+ reconcileInstallPackages(requests, versionInfos);
+ if (reconciledPackages != null
+ && renameAndUpdatePaths(requests)
+ && commitInstallPackages(reconciledPackages)) {
+ success = true;
+ }
+ }
+ } finally {
+ completeInstallProcess(requests, createdAppId, success);
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
+ }
+
+ private boolean renameAndUpdatePaths(List<InstallRequest> requests) {
+ try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
for (InstallRequest request : requests) {
+ ParsedPackage parsedPackage = request.getParsedPackage();
+ final boolean isApex = (request.getScanFlags() & SCAN_AS_APEX) != 0;
+ if (isApex) {
+ continue;
+ }
try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage");
- request.onPrepareStarted();
- preparePackageLI(request);
- } catch (PrepareFailure prepareFailure) {
- request.setError(prepareFailure.error,
- prepareFailure.getMessage());
- request.setOriginPackage(prepareFailure.mConflictingPackage);
- request.setOriginPermission(prepareFailure.mConflictingPermission);
- return;
- } finally {
- request.onPrepareFinished();
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ doRenameLI(request, parsedPackage);
+ setUpFsVerity(parsedPackage);
+ } catch (Installer.InstallerException | IOException | DigestException
+ | NoSuchAlgorithmException | PrepareFailure e) {
+ request.setError(PackageManagerException.INTERNAL_ERROR_VERITY_SETUP,
+ "Failed to set up verity: " + e);
+ return false;
}
+ // update paths that are set before renaming
+ PackageSetting scannedPackageSetting = request.getScannedPackageSetting();
+ scannedPackageSetting.setPath(new File(parsedPackage.getPath()));
+ scannedPackageSetting.setLegacyNativeLibraryPath(
+ parsedPackage.getNativeLibraryRootDir());
+ }
+ return true;
+ }
+ }
+
+ private boolean prepareInstallPackages(List<InstallRequest> requests) {
+ for (InstallRequest request : requests) {
+ try {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage");
+ request.onPrepareStarted();
+ preparePackage(request);
+ } catch (PrepareFailure prepareFailure) {
+ request.setError(prepareFailure.error,
+ prepareFailure.getMessage());
+ request.setOriginPackage(prepareFailure.mConflictingPackage);
+ request.setOriginPermission(prepareFailure.mConflictingPermission);
+ return false;
+ } finally {
+ request.onPrepareFinished();
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
+ }
+ return true;
+ }
+
+ private boolean scanInstallPackages(List<InstallRequest> requests,
+ Map<String, Boolean> createdAppId, Map<String, Settings.VersionInfo> versionInfos) {
+ // TODO(b/362840929): remove locker
+ try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
+ final Set<String> scannedPackages = new ArraySet<>(requests.size());
+ for (InstallRequest request : requests) {
final ParsedPackage packageToScan = request.getParsedPackage();
if (packageToScan == null) {
request.setError(INSTALL_FAILED_SESSION_INVALID,
"Failed to obtain package to scan");
- return;
+ return false;
}
request.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
final String packageName = packageToScan.getPackageName();
@@ -1064,7 +1107,7 @@
"Duplicate package "
+ packageName
+ " in multi-package install request.");
- return;
+ return false;
}
if (!checkNoAppStorageIsConsistent(
request.getScanRequestOldPackage(), packageToScan)) {
@@ -1074,7 +1117,7 @@
INSTALL_FAILED_UPDATE_INCOMPATIBLE,
"Update attempted to change value of "
+ PackageManager.PROPERTY_NO_APP_DATA_STORAGE);
- return;
+ return false;
}
final boolean isApex = (request.getScanFlags() & SCAN_AS_APEX) != 0;
final boolean isSdkLibrary = packageToScan.isSdkLibrary();
@@ -1087,7 +1130,7 @@
mPm.getSettingsVersionForPackage(packageToScan));
} catch (PackageManagerException e) {
request.setError("Scanning Failed.", e);
- return;
+ return false;
}
if (request.isArchived()) {
final SparseArray<String> responsibleInstallerTitles =
@@ -1099,17 +1142,22 @@
request.setError(PackageManagerException.ofInternalError(
"Failed to obtain the responsible installer info",
INTERNAL_ERROR_ARCHIVE_NO_INSTALLER_TITLE));
- return;
+ return false;
}
request.setResponsibleInstallerTitles(responsibleInstallerTitles);
}
}
+ }
+ return true;
+ }
- List<ReconciledPackage> reconciledPackages;
+ private List<ReconciledPackage> reconcileInstallPackages(List<InstallRequest> requests,
+ Map<String, Settings.VersionInfo> versionInfos) {
+ try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
synchronized (mPm.mLock) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages");
- reconciledPackages = ReconcilePackageUtils.reconcilePackages(
+ return ReconcilePackageUtils.reconcilePackages(
requests, Collections.unmodifiableMap(mPm.mPackages),
versionInfos, mSharedLibraries, mPm.mSettings.getKeySetManagerService(),
mPm.mSettings, mPm.mInjector.getSystemConfig());
@@ -1117,70 +1165,80 @@
for (InstallRequest request : requests) {
request.setError("Reconciliation failed...", e);
}
- return;
+ return null;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
- if (Flags.improveInstallFreeze()) {
- // Postpone freezer until after reconcile
- for (ReconciledPackage reconciledPkg : reconciledPackages) {
- InstallRequest installRequest = reconciledPkg.mInstallRequest;
- String packageName = installRequest.getParsedPackage().getPackageName();
- PackageFreezer freezer = freezePackageForInstall(packageName,
- UserHandle.USER_ALL, installRequest.getInstallFlags(),
- "installPackageLI", ApplicationExitInfo.REASON_PACKAGE_UPDATED,
- installRequest);
- installRequest.setFreezer(freezer);
- }
+ }
+ }
+ }
+
+
+ private boolean commitInstallPackages(List<ReconciledPackage> reconciledPackages) {
+ try (PackageManagerTracedLock installLock = mPm.mInstallLock.acquireLock()) {
+ if (Flags.improveInstallFreeze()) {
+ // Postpone freezer until after reconcile
+ for (ReconciledPackage reconciledPkg : reconciledPackages) {
+ InstallRequest installRequest = reconciledPkg.mInstallRequest;
+ String packageName = installRequest.getParsedPackage().getPackageName();
+ PackageFreezer freezer = freezePackageForInstall(packageName,
+ UserHandle.USER_ALL, installRequest.getInstallFlags(),
+ "installPackageLI", ApplicationExitInfo.REASON_PACKAGE_UPDATED,
+ installRequest);
+ installRequest.setFreezer(freezer);
}
+ }
+ synchronized (mPm.mLock) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "commitPackages");
commitPackagesLocked(reconciledPackages, mPm.mUserManager.getUserIds());
- success = true;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
executePostCommitStepsLIF(reconciledPackages);
- } finally {
- if (success) {
- for (InstallRequest request : requests) {
- if (request.getDataLoaderType() != DataLoaderType.INCREMENTAL) {
- continue;
- }
- if (request.getSignatureSchemeVersion() != SIGNING_BLOCK_V4) {
- continue;
- }
- // For incremental installs, we bypass the verifier prior to install. Now
- // that we know the package is valid, send a notice to the verifier with
- // the root hash of the base.apk.
- final String baseCodePath = request.getPkg().getBaseApkPath();
- final String[] splitCodePaths = request.getPkg().getSplitCodePaths();
- final Uri originUri = request.getOriginUri();
- final int verificationId = mPm.mPendingVerificationToken++;
- final String rootHashString = PackageManagerServiceUtils
- .buildVerificationRootHashString(baseCodePath, splitCodePaths);
- VerificationUtils.broadcastPackageVerified(verificationId, originUri,
- PackageManager.VERIFICATION_ALLOW, rootHashString,
- request.getDataLoaderType(), request.getUser(), mContext);
+ }
+ return true;
+ }
+
+ private void completeInstallProcess(List<InstallRequest> requests,
+ Map<String, Boolean> createdAppId, boolean success) {
+ if (success) {
+ for (InstallRequest request : requests) {
+ if (request.getDataLoaderType() != DataLoaderType.INCREMENTAL) {
+ continue;
}
- } else {
- for (InstallRequest installRequest : requests) {
- if (installRequest.getParsedPackage() != null && createdAppId.getOrDefault(
- installRequest.getParsedPackage().getPackageName(), false)) {
- cleanUpAppIdCreation(installRequest);
- }
+ if (request.getSignatureSchemeVersion() != SIGNING_BLOCK_V4) {
+ continue;
}
- // TODO(b/194319951): create a more descriptive reason than unknown
- // mark all non-failure installs as UNKNOWN so we do not treat them as success
- for (InstallRequest request : requests) {
- request.closeFreezer();
- if (request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED) {
- request.setReturnCode(PackageManager.INSTALL_UNKNOWN);
- }
+ // For incremental installs, we bypass the verifier prior to install. Now
+ // that we know the package is valid, send a notice to the verifier with
+ // the root hash of the base.apk.
+ final String baseCodePath = request.getPkg().getBaseApkPath();
+ final String[] splitCodePaths = request.getPkg().getSplitCodePaths();
+ final Uri originUri = request.getOriginUri();
+ final int verificationId = mPm.mPendingVerificationToken++;
+ final String rootHashString = PackageManagerServiceUtils
+ .buildVerificationRootHashString(baseCodePath, splitCodePaths);
+ VerificationUtils.broadcastPackageVerified(verificationId, originUri,
+ PackageManager.VERIFICATION_ALLOW, rootHashString,
+ request.getDataLoaderType(), request.getUser(), mContext);
+ }
+ } else {
+ for (InstallRequest installRequest : requests) {
+ if (installRequest.getParsedPackage() != null && createdAppId.getOrDefault(
+ installRequest.getParsedPackage().getPackageName(), false)) {
+ cleanUpAppIdCreation(installRequest);
}
}
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ // TODO(b/194319951): create a more descriptive reason than unknown
+ // mark all non-failure installs as UNKNOWN so we do not treat them as success
+ for (InstallRequest request : requests) {
+ request.closeFreezer();
+ if (request.getReturnCode() == PackageManager.INSTALL_SUCCEEDED) {
+ request.setReturnCode(PackageManager.INSTALL_UNKNOWN);
+ }
+ }
}
}
@@ -1200,8 +1258,7 @@
return newProp != null && newProp.getBoolean();
}
- @GuardedBy("mPm.mInstallLock")
- private void preparePackageLI(InstallRequest request) throws PrepareFailure {
+ private void preparePackage(InstallRequest request) throws PrepareFailure {
final int[] allUsers = mPm.mUserManager.getUserIds();
final int installFlags = request.getInstallFlags();
final boolean onExternal = request.getVolumeUuid() != null;
@@ -1708,18 +1765,7 @@
}
}
- if (!isApex) {
- doRenameLI(request, parsedPackage);
-
- try {
- setUpFsVerity(parsedPackage);
- } catch (Installer.InstallerException | IOException | DigestException
- | NoSuchAlgorithmException e) {
- throw PrepareFailure.ofInternalError(
- "Failed to set up verity: " + e,
- PackageManagerException.INTERNAL_ERROR_VERITY_SETUP);
- }
- } else {
+ if (isApex) {
// Use the path returned by apexd
parsedPackage.setPath(request.getApexInfo().modulePath);
parsedPackage.setBaseApkPath(request.getApexInfo().modulePath);
@@ -1851,10 +1897,16 @@
}
if (!oldSharedUid.equals(newSharedUid)) {
- throw new PrepareFailure(INSTALL_FAILED_UID_CHANGED,
- "Package " + parsedPackage.getPackageName()
- + " shared user changed from "
- + oldSharedUid + " to " + newSharedUid);
+ if (!(oldSharedUid.equals("<nothing>") && ps.getPkg() == null
+ && ps.isArchivedOnAnyUser(allUsers))) {
+ // Only allow changing sharedUserId if unarchiving
+ // TODO(b/361558423): remove this check after pre-archiving installs
+ // accept a sharedUserId param in the API
+ throw new PrepareFailure(INSTALL_FAILED_UID_CHANGED,
+ "Package " + parsedPackage.getPackageName()
+ + " shared user changed from "
+ + oldSharedUid + " to " + newSharedUid);
+ }
}
// APK should not re-join shared UID
@@ -2055,7 +2107,21 @@
// Reflect the rename in scanned details
try {
- parsedPackage.setPath(afterCodeFile.getCanonicalPath());
+ String afterCanonicalPath = afterCodeFile.getCanonicalPath();
+ String beforeCanonicalPath = beforeCodeFile.getCanonicalPath();
+ parsedPackage.setPath(afterCanonicalPath);
+
+ parsedPackage.setNativeLibraryDir(
+ parsedPackage.getNativeLibraryDir()
+ .replace(beforeCanonicalPath, afterCanonicalPath));
+ parsedPackage.setNativeLibraryRootDir(
+ parsedPackage.getNativeLibraryRootDir()
+ .replace(beforeCanonicalPath, afterCanonicalPath));
+ String secondaryNativeLibraryDir = parsedPackage.getSecondaryNativeLibraryDir();
+ if (secondaryNativeLibraryDir != null) {
+ parsedPackage.setSecondaryNativeLibraryDir(
+ secondaryNativeLibraryDir.replace(beforeCanonicalPath, afterCanonicalPath));
+ }
} catch (IOException e) {
Slog.e(TAG, "Failed to get path: " + afterCodeFile, e);
throw new PrepareFailure(PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE,
@@ -2600,70 +2666,8 @@
pkg.getBaseApkPath(), pkg.getSplitCodePaths());
}
- // Construct the DexoptOptions early to see if we should skip running dexopt.
- //
- // Do not run PackageDexOptimizer through the local performDexOpt
- // method because `pkg` may not be in `mPackages` yet.
- //
- // Also, don't fail application installs if the dexopt step fails.
- DexoptOptions dexoptOptions = DexOptHelper.getDexoptOptionsByInstallRequest(
- installRequest, mDexManager);
- // Check whether we need to dexopt the app.
- //
- // NOTE: it is IMPORTANT to call dexopt:
- // - after doRename which will sync the package data from AndroidPackage and
- // its corresponding ApplicationInfo.
- // - after installNewPackageLIF or replacePackageLIF which will update result with the
- // uid of the application (pkg.applicationInfo.uid).
- // This update happens in place!
- //
- // We only need to dexopt if the package meets ALL of the following conditions:
- // 1) it is not an instant app or if it is then dexopt is enabled via gservices.
- // 2) it is not debuggable.
- // 3) it is not on Incremental File System.
- //
- // Note that we do not dexopt instant apps by default. dexopt can take some time to
- // complete, so we skip this step during installation. Instead, we'll take extra time
- // the first time the instant app starts. It's preferred to do it this way to provide
- // continuous progress to the useur instead of mysteriously blocking somewhere in the
- // middle of running an instant app. The default behaviour can be overridden
- // via gservices.
- //
- // Furthermore, dexopt may be skipped, depending on the install scenario and current
- // state of the device.
- //
- // TODO(b/174695087): instantApp and onIncremental should be removed and their install
- // path moved to SCENARIO_FAST.
-
- final boolean performDexopt = DexOptHelper.shouldPerformDexopt(installRequest,
- dexoptOptions, mContext);
- if (performDexopt) {
- // dexopt can take long, and ArtService doesn't require installd, so we release
- // the lock here and re-acquire the lock after dexopt is finished.
- PackageManagerTracedLock.RawLock installLock = mPm.mInstallLock.getRawLock();
- installLock.unlock();
- try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
-
- // This mirrors logic from commitReconciledScanResultLocked, where the library
- // files needed for dexopt are assigned.
- PackageSetting realPkgSetting = installRequest.getRealPackageSetting();
-
- // Unfortunately, the updated system app flag is only tracked on this
- // PackageSetting
- boolean isUpdatedSystemApp =
- installRequest.getScannedPackageSetting().isUpdatedSystemApp();
-
- realPkgSetting.getPkgState().setUpdatedSystemApp(isUpdatedSystemApp);
-
- DexoptResult dexOptResult = DexOptHelper.dexoptPackageUsingArtService(
- installRequest, dexoptOptions);
- installRequest.onDexoptFinished(dexOptResult);
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- } finally {
- installLock.lock();
- }
- }
+ DexOptHelper.performDexoptIfNeeded(installRequest, mDexManager, mContext,
+ mPm.mInstallLock.getRawLock());
}
PackageManagerServiceUtils.waitForNativeBinariesExtractionForIncremental(
incrementalStorages);
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index d374142..9428de7 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -42,6 +42,7 @@
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.IntArray;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
@@ -924,6 +925,18 @@
return PackageArchiver.isArchived(readUserState(userId));
}
+ /**
+ * @return if the package is archived in any of the users
+ */
+ boolean isArchivedOnAnyUser(int[] userIds) {
+ for (int user : userIds) {
+ if (isArchived(user)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
int getInstallReason(int userId) {
return readUserState(userId).getInstallReason();
}
@@ -981,39 +994,23 @@
}
int[] queryInstalledUsers(int[] users, boolean installed) {
- int num = 0;
+ IntArray installedUsers = new IntArray(users.length);
for (int user : users) {
if (getInstalled(user) == installed) {
- num++;
+ installedUsers.add(user);
}
}
- int[] res = new int[num];
- num = 0;
- for (int user : users) {
- if (getInstalled(user) == installed) {
- res[num] = user;
- num++;
- }
- }
- return res;
+ return installedUsers.toArray();
}
int[] queryUsersInstalledOrHasData(int[] users) {
- int num = 0;
+ IntArray usersInstalledOrHasData = new IntArray(users.length);
for (int user : users) {
if (getInstalled(user) || readUserState(user).dataExists()) {
- num++;
+ usersInstalledOrHasData.add(user);
}
}
- int[] res = new int[num];
- num = 0;
- for (int user : users) {
- if (getInstalled(user) || readUserState(user).dataExists()) {
- res[num] = user;
- num++;
- }
- }
- return res;
+ return usersInstalledOrHasData.toArray();
}
long getCeDataInode(int userId) {
@@ -1283,25 +1280,14 @@
}
public int[] getNotInstalledUserIds() {
- int count = 0;
int userStateCount = mUserStates.size();
+ IntArray notInstalledUsers = new IntArray(userStateCount);
for (int i = 0; i < userStateCount; i++) {
if (!mUserStates.valueAt(i).isInstalled()) {
- count++;
+ notInstalledUsers.add(mUserStates.keyAt(i));
}
}
- if (count == 0) {
- return EmptyArray.INT;
- }
-
- int[] excludedUserIds = new int[count];
- int idx = 0;
- for (int i = 0; i < userStateCount; i++) {
- if (!mUserStates.valueAt(i).isInstalled()) {
- excludedUserIds[idx++] = mUserStates.keyAt(i);
- }
- }
- return excludedUserIds;
+ return notInstalledUsers.toArray();
}
/**
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index 26da84f..f9a8968 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -292,8 +292,10 @@
// Step 2: destroy app data.
mAppDataHelper.destroyAppDataLIF(resolvedPkg, userId, appDataDeletionFlags);
if (userId != UserHandle.USER_ALL) {
- ps.setCeDataInode(-1, userId);
- ps.setDeDataInode(-1, userId);
+ synchronized (mPm.mLock) {
+ ps.setCeDataInode(-1, userId);
+ ps.setDeDataInode(-1, userId);
+ }
}
final PreferredActivityHelper preferredActivityHelper = new PreferredActivityHelper(mPm,
@@ -425,19 +427,21 @@
}
final boolean isArchive = (flags & PackageManager.DELETE_ARCHIVE) != 0;
final long currentTimeMillis = System.currentTimeMillis();
- for (int userId : outInfo.mRemovedUsers) {
- if (DEBUG_REMOVE) {
- final boolean wasInstalled = deletedPs.getInstalled(userId);
- Slog.d(TAG, " user " + userId + ": " + wasInstalled + " => " + false);
+ synchronized (mPm.mLock) {
+ for (int userId : outInfo.mRemovedUsers) {
+ if (DEBUG_REMOVE) {
+ final boolean wasInstalled = deletedPs.getInstalled(userId);
+ Slog.d(TAG, " user " + userId + ": " + wasInstalled + " => " + false);
+ }
+ deletedPs.setInstalled(/* installed= */ false, userId);
}
- deletedPs.setInstalled(/* installed= */ false, userId);
- }
- // Preserve split apk information for downgrade check with DELETE_KEEP_DATA and archived
- // app cases
- if (deletedPkg != null && deletedPkg.getSplitNames() != null) {
- deletedPs.setSplitNames(deletedPkg.getSplitNames());
- deletedPs.setSplitRevisionCodes(deletedPkg.getSplitRevisionCodes());
+ // Preserve split apk information for downgrade check with DELETE_KEEP_DATA and
+ // archived app cases
+ if (deletedPkg != null && deletedPkg.getSplitNames() != null) {
+ deletedPs.setSplitNames(deletedPkg.getSplitNames());
+ deletedPs.setSplitRevisionCodes(deletedPkg.getSplitRevisionCodes());
+ }
}
}
@@ -448,17 +452,19 @@
if (DEBUG_REMOVE) {
Slog.d(TAG, "Propagating install state across downgrade");
}
- for (int userId : allUserHandles) {
- final boolean installed = ArrayUtils.contains(outInfo.mOrigUsers, userId);
- if (DEBUG_REMOVE) {
- Slog.d(TAG, " user " + userId + " => " + installed);
- }
- if (installed != deletedPs.getInstalled(userId)) {
- installedStateChanged = true;
- }
- deletedPs.setInstalled(installed, userId);
- if (installed) {
- deletedPs.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userId);
+ synchronized (mPm.mLock) {
+ for (int userId : allUserHandles) {
+ final boolean installed = ArrayUtils.contains(outInfo.mOrigUsers, userId);
+ if (DEBUG_REMOVE) {
+ Slog.d(TAG, " user " + userId + " => " + installed);
+ }
+ if (installed != deletedPs.getInstalled(userId)) {
+ installedStateChanged = true;
+ }
+ deletedPs.setInstalled(installed, userId);
+ if (installed) {
+ deletedPs.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userId);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 74594cc..94bdfbd 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -56,8 +56,8 @@
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageStateUtils;
+import com.android.server.rollback.ApexdRevertLogger;
import com.android.server.rollback.RollbackManagerInternal;
-import com.android.server.rollback.WatchdogRollbackLogger;
import java.io.BufferedReader;
import java.io.BufferedWriter;
@@ -764,7 +764,7 @@
private void logFailedApexSessionsIfNecessary() {
synchronized (mFailedPackageNames) {
if (!mFailedPackageNames.isEmpty()) {
- WatchdogRollbackLogger.logApexdRevert(mContext,
+ ApexdRevertLogger.logApexdRevert(mContext,
mFailedPackageNames, mNativeFailureReason);
}
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 13901c1..a683a8c 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1194,11 +1194,11 @@
// Avoid marking pre-created users for removal.
return;
}
- if (ui.lastLoggedInTime == 0) {
- // Avoid marking a not-yet-logged-in ephemeral user for removal, since it doesn't have
- // any personal data in it yet due to not being logged in.
- // This will also avoid marking an auto-created not-yet-logged-in ephemeral guest user
- // for removal, which would be recreated again later in the boot anyway.
+ if (ui.lastLoggedInTime == 0 && ui.isGuest() && Resources.getSystem().getBoolean(
+ com.android.internal.R.bool.config_guestUserAutoCreated)) {
+ // Avoid marking auto-created but not-yet-logged-in guest user for removal. Because a
+ // new one will be created anyway, and this one doesn't have any personal data in it yet
+ // due to not being logged in.
return;
}
// Mark the user for removal.
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index 1c70af0..5ca5fda 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -397,6 +397,8 @@
ai.privateFlags |= flag(state.isInstantApp(), ApplicationInfo.PRIVATE_FLAG_INSTANT)
| flag(state.isVirtualPreload(), ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD)
| flag(state.isHidden(), ApplicationInfo.PRIVATE_FLAG_HIDDEN);
+ ai.privateFlagsExt |=
+ flag(state.isNotLaunched(), ApplicationInfo.PRIVATE_FLAG_EXT_NOT_LAUNCHED);
if (state.getEnabledState() == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
ai.enabled = true;
} else if (state.getEnabledState()
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 6c78b3c..6e7a009 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1366,7 +1366,7 @@
for (int requestedPermissionNum = 0; requestedPermissionNum < numRequestedPermissions;
requestedPermissionNum++) {
- String permission = requestedPermissions[requestedPermissionNum];
+ String permission = sortedRequestedPermissions[requestedPermissionNum];
// If there is a disabled system app it may request a permission the updated
// version ot the data partition doesn't, In this case skip the permission.
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 46e6546..df9f7fb 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -26,7 +26,6 @@
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_ERRORED;
import static android.app.AppOpsManager.MODE_IGNORED;
-import static android.app.AppOpsManager.OP_BLUETOOTH_CONNECT;
import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISALLOWED;
import static android.content.pm.ApplicationInfo.AUTO_REVOKE_DISCOURAGED;
import static android.permission.flags.Flags.serverSideAttributionRegistration;
@@ -1640,22 +1639,7 @@
throw new SecurityException(msg + ":" + e.getMessage());
}
}
- int result = Math.max(checkedOpResult, notedOpResult);
- // TODO(b/302609140): Remove extra logging after this issue is diagnosed.
- if (op == OP_BLUETOOTH_CONNECT && result == MODE_ERRORED) {
- if (result == checkedOpResult) {
- Slog.e(LOG_TAG, "BLUETOOTH_CONNECT permission hard denied as"
- + " checkOp for resolvedAttributionSource "
- + resolvedAttributionSource + " and op " + op
- + " returned MODE_ERRORED");
- } else {
- Slog.e(LOG_TAG, "BLUETOOTH_CONNECT permission hard denied as"
- + " noteOp for resolvedAttributionSource "
- + resolvedAttributionSource + " and op " + notedOp
- + " returned MODE_ERRORED");
- }
- }
- return result;
+ return Math.max(checkedOpResult, notedOpResult);
}
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index f96706e..ed9dcfa 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -16,6 +16,7 @@
package com.android.server.policy;
+import static android.Manifest.permission.CREATE_VIRTUAL_DEVICE;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW;
import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
@@ -59,13 +60,18 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
+import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD;
@@ -529,7 +535,7 @@
volatile boolean mRequestedOrSleepingDefaultDisplay;
/**
- * This is used to check whether to invoke {@link #updateScreenOffSleepToken} when screen is
+ * This is used to check whether to acquire screen-off sleep token when screen is
* turned off. E.g. if it is false when screen is turned off and the display is swapping, it
* is expected that the screen will be on in a short time. Then it is unnecessary to acquire
* screen-off-sleep-token, so it can avoid intermediate visibility or lifecycle changes.
@@ -604,7 +610,6 @@
private boolean mPendingKeyguardOccluded;
private boolean mKeyguardOccludedChanged;
- private ActivityTaskManagerInternal.SleepTokenAcquirer mScreenOffSleepTokenAcquirer;
Intent mHomeIntent;
Intent mCarDockIntent;
Intent mDeskDockIntent;
@@ -804,7 +809,7 @@
event.recycle();
break;
case MSG_HANDLE_ALL_APPS:
- launchAllAppsAction();
+ launchAllAppsAction((KeyEvent) msg.obj);
break;
case MSG_RINGER_TOGGLE_CHORD:
handleRingerChordGesture();
@@ -1873,26 +1878,31 @@
}
}
- private void launchAllAppsAction() {
- Intent intent = new Intent(Intent.ACTION_ALL_APPS);
- if (mHasFeatureLeanback) {
- Intent intentLauncher = new Intent(Intent.ACTION_MAIN);
- intentLauncher.addCategory(Intent.CATEGORY_HOME);
- ResolveInfo resolveInfo = mPackageManager.resolveActivityAsUser(intentLauncher,
- PackageManager.MATCH_SYSTEM_ONLY,
- mCurrentUserId);
- if (resolveInfo != null) {
- intent.setPackage(resolveInfo.activityInfo.packageName);
+ private void launchAllAppsAction(KeyEvent event) {
+ if (mHasFeatureLeanback || mHasFeatureWatch) {
+ // TV and watch support the all apps intent
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS);
+ Intent intent = new Intent(Intent.ACTION_ALL_APPS);
+ if (mHasFeatureLeanback) {
+ Intent intentLauncher = new Intent(Intent.ACTION_MAIN);
+ intentLauncher.addCategory(Intent.CATEGORY_HOME);
+ ResolveInfo resolveInfo = mPackageManager.resolveActivityAsUser(intentLauncher,
+ PackageManager.MATCH_SYSTEM_ONLY,
+ mCurrentUserId);
+ if (resolveInfo != null) {
+ intent.setPackage(resolveInfo.activityInfo.packageName);
+ }
}
- }
- startActivityAsUser(intent, UserHandle.CURRENT);
- }
-
- private void launchAllAppsViaA11y() {
- AccessibilityManagerInternal accessibilityManager = getAccessibilityManagerInternal();
- if (accessibilityManager != null) {
- accessibilityManager.performSystemAction(
- AccessibilityService.GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS);
+ startActivityAsUser(intent, UserHandle.CURRENT);
+ } else {
+ notifyKeyGestureCompleted(event,
+ KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS);
+ AccessibilityManagerInternal accessibilityManager = getAccessibilityManagerInternal();
+ if (accessibilityManager != null) {
+ accessibilityManager.performSystemAction(
+ AccessibilityService.GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS);
+ }
}
dismissKeyboardShortcutsMenu();
}
@@ -2070,15 +2080,7 @@
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, "Home - Long Press");
switch (mLongPressOnHomeBehavior) {
case LONG_PRESS_HOME_ALL_APPS:
- if (mHasFeatureLeanback) {
- launchAllAppsAction();
- notifyKeyGestureCompleted(event,
- KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS);
- } else {
- launchAllAppsViaA11y();
- notifyKeyGestureCompleted(event,
- KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS);
- }
+ launchAllAppsAction(event);
break;
case LONG_PRESS_HOME_ASSIST:
notifyKeyGestureCompleted(event,
@@ -2217,9 +2219,6 @@
mLockPatternUtils = new LockPatternUtils(mContext);
mLogger = new MetricsLogger();
- mScreenOffSleepTokenAcquirer = mActivityTaskManagerInternal
- .createSleepTokenAcquirer("ScreenOff");
-
Resources res = mContext.getResources();
mWakeOnDpadKeyPress =
res.getBoolean(com.android.internal.R.bool.config_wakeOnDpadKeyPress);
@@ -3058,7 +3057,7 @@
/** {@inheritDoc} */
@Override
public int checkAddPermission(int type, boolean isRoundedCornerOverlay, String packageName,
- int[] outAppOp) {
+ int[] outAppOp, int displayId) {
if (isRoundedCornerOverlay && mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
!= PERMISSION_GRANTED) {
return ADD_PERMISSION_DENIED;
@@ -3098,6 +3097,12 @@
case TYPE_VOICE_INTERACTION:
case TYPE_QS_DIALOG:
case TYPE_NAVIGATION_BAR_PANEL:
+ case TYPE_STATUS_BAR:
+ case TYPE_NOTIFICATION_SHADE:
+ case TYPE_NAVIGATION_BAR:
+ case TYPE_STATUS_BAR_ADDITIONAL:
+ case TYPE_STATUS_BAR_SUB_PANEL:
+ case TYPE_VOICE_INTERACTION_STARTING:
// The window manager will check these.
return ADD_OKAY;
}
@@ -3141,6 +3146,13 @@
return ADD_OKAY;
}
+ // Allow virtual device owners to add overlays on the displays they own.
+ if (mWindowManagerFuncs.isCallerVirtualDeviceOwner(displayId, callingUid)
+ && mContext.checkCallingOrSelfPermission(CREATE_VIRTUAL_DEVICE)
+ == PERMISSION_GRANTED) {
+ return ADD_OKAY;
+ }
+
// check if user has enabled this operation. SecurityException will be thrown if this app
// has not been allowed by the user. The reason to use "noteOp" (instead of checkOp) is to
// make sure the usage is logged.
@@ -3581,18 +3593,6 @@
if (down) {
int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
- // Disable autobrightness if it's on
- int auto = Settings.System.getIntForUser(
- mContext.getContentResolver(),
- Settings.System.SCREEN_BRIGHTNESS_MODE,
- Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
- UserHandle.USER_CURRENT_OR_SELF);
- if (auto != 0) {
- Settings.System.putIntForUser(mContext.getContentResolver(),
- Settings.System.SCREEN_BRIGHTNESS_MODE,
- Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
- UserHandle.USER_CURRENT_OR_SELF);
- }
int screenDisplayId = displayId < 0 ? DEFAULT_DISPLAY : displayId;
float minLinearBrightness = mPowerManager.getBrightnessConstraint(
@@ -3688,18 +3688,11 @@
break;
case KeyEvent.KEYCODE_ALL_APPS:
if (firstDown) {
- if (mHasFeatureLeanback) {
- mHandler.removeMessages(MSG_HANDLE_ALL_APPS);
- Message msg = mHandler.obtainMessage(MSG_HANDLE_ALL_APPS);
- msg.setAsynchronous(true);
- msg.sendToTarget();
- notifyKeyGestureCompleted(event,
- KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS);
- } else {
- launchAllAppsViaA11y();
- notifyKeyGestureCompleted(event,
- KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS);
- }
+ mHandler.removeMessages(MSG_HANDLE_ALL_APPS);
+
+ Message msg = mHandler.obtainMessage(MSG_HANDLE_ALL_APPS, new KeyEvent(event));
+ msg.setAsynchronous(true);
+ msg.sendToTarget();
}
return true;
case KeyEvent.KEYCODE_NOTIFICATION:
@@ -3752,9 +3745,7 @@
KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_CAPS_LOCK);
} else if (mPendingMetaAction) {
if (!canceled) {
- launchAllAppsViaA11y();
- notifyKeyGestureCompleted(event,
- KeyGestureEvent.KEY_GESTURE_TYPE_ACCESSIBILITY_ALL_APPS);
+ launchAllAppsAction(event);
}
mPendingMetaAction = false;
}
@@ -5526,13 +5517,6 @@
mRequestedOrSleepingDefaultDisplay = true;
mIsGoingToSleepDefaultDisplay = true;
- // In case startedGoingToSleep is called after screenTurnedOff (the source caller is in
- // order but the methods run on different threads) and updateScreenOffSleepToken was
- // skipped. Then acquire sleep token if screen was off.
- if (!mDefaultDisplayPolicy.isScreenOnFully() && !mDefaultDisplayPolicy.isScreenOnEarly()) {
- updateScreenOffSleepToken(true /* acquire */);
- }
-
if (mKeyguardDelegate != null) {
mKeyguardDelegate.onStartedGoingToSleep(pmSleepReason);
}
@@ -5693,11 +5677,9 @@
if (DEBUG_WAKEUP) Slog.i(TAG, "Display" + displayId + " turned off...");
if (displayId == DEFAULT_DISPLAY) {
- if (!isSwappingDisplay || mIsGoingToSleepDefaultDisplay) {
- updateScreenOffSleepToken(true /* acquire */);
- }
+ final boolean acquireSleepToken = !isSwappingDisplay || mIsGoingToSleepDefaultDisplay;
mRequestedOrSleepingDefaultDisplay = false;
- mDefaultDisplayPolicy.screenTurnedOff();
+ mDefaultDisplayPolicy.screenTurnedOff(acquireSleepToken);
synchronized (mLock) {
if (mKeyguardDelegate != null) {
mKeyguardDelegate.onScreenTurnedOff();
@@ -5753,7 +5735,6 @@
if (displayId == DEFAULT_DISPLAY) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenTurningOn",
0 /* cookie */);
- updateScreenOffSleepToken(false /* acquire */);
mDefaultDisplayPolicy.screenTurningOn(screenOnListener);
mBootAnimationDismissable = false;
@@ -6260,15 +6241,6 @@
}
}
- // TODO (multidisplay): Support multiple displays in WindowManagerPolicy.
- private void updateScreenOffSleepToken(boolean acquire) {
- if (acquire) {
- mScreenOffSleepTokenAcquirer.acquire(DEFAULT_DISPLAY);
- } else {
- mScreenOffSleepTokenAcquirer.release(DEFAULT_DISPLAY);
- }
- }
-
/** {@inheritDoc} */
@Override
public void enableScreenAfterBoot() {
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 989c8a8..892af6b 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -362,6 +362,12 @@
* Invoked when a screenshot is taken of the given display to notify registered listeners.
*/
List<ComponentName> notifyScreenshotListeners(int displayId);
+
+ /**
+ * Returns whether the given UID is the owner of a virtual device, which the given display
+ * belongs to.
+ */
+ boolean isCallerVirtualDeviceOwner(int displayId, int callingUid);
}
/**
@@ -421,6 +427,7 @@
* @param packageName package name
* @param outAppOp First element will be filled with the app op corresponding to
* this window, or OP_NONE.
+ * @param displayId The display on which this window is being added.
*
* @return {@link WindowManagerGlobal#ADD_OKAY} if the add can proceed;
* else an error code, usually
@@ -429,7 +436,7 @@
* @see WindowManager.LayoutParams#PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY
*/
int checkAddPermission(int type, boolean isRoundedCornerOverlay, String packageName,
- int[] outAppOp);
+ int[] outAppOp, int displayId);
/**
* After the window manager has computed the current configuration based
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 12e7fd0..71cb882 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -3668,7 +3668,7 @@
mBrightWhenDozingConfig);
int wakefulness = powerGroup.getWakefulnessLocked();
if (DEBUG_SPEW) {
- Slog.d(TAG, "updateDisplayPowerStateLocked: displayReady=" + ready
+ Slog.d(TAG, "updatePowerGroupsLocked: displayReady=" + ready
+ ", groupId=" + groupId
+ ", policy=" + policyToString(powerGroup.getPolicyLocked())
+ ", mWakefulness="
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
index 822ec2e..6847a5c 100644
--- a/services/core/java/com/android/server/power/ThermalManagerService.java
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -54,6 +54,7 @@
import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.Temperature;
+import android.os.Trace;
import android.util.ArrayMap;
import android.util.EventLog;
import android.util.Slog;
@@ -247,6 +248,7 @@
private void setStatusLocked(int newStatus) {
if (newStatus != mStatus) {
+ Trace.traceCounter(Trace.TRACE_TAG_POWER, "ThermalManagerService.status", newStatus);
mStatus = newStatus;
notifyStatusListenersLocked();
}
diff --git a/services/core/java/com/android/server/power/stats/AggregatedPowerStatsSection.java b/services/core/java/com/android/server/power/stats/AggregatedPowerStatsSection.java
deleted file mode 100644
index 7ba4330..0000000
--- a/services/core/java/com/android/server/power/stats/AggregatedPowerStatsSection.java
+++ /dev/null
@@ -1,48 +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.server.power.stats;
-
-import android.util.IndentingPrintWriter;
-
-import com.android.modules.utils.TypedXmlSerializer;
-
-import java.io.IOException;
-
-class AggregatedPowerStatsSection extends PowerStatsSpan.Section {
- public static final String TYPE = "aggregated-power-stats";
-
- private final AggregatedPowerStats mAggregatedPowerStats;
-
- AggregatedPowerStatsSection(AggregatedPowerStats aggregatedPowerStats) {
- super(TYPE);
- mAggregatedPowerStats = aggregatedPowerStats;
- }
-
- public AggregatedPowerStats getAggregatedPowerStats() {
- return mAggregatedPowerStats;
- }
-
- @Override
- void write(TypedXmlSerializer serializer) throws IOException {
- mAggregatedPowerStats.writeXml(serializer);
- }
-
- @Override
- public void dump(IndentingPrintWriter ipw) {
- mAggregatedPowerStats.dump(ipw);
- }
-}
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 385561d..680b1ac 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -23,8 +23,6 @@
import static android.os.BatteryStatsManager.NUM_WIFI_STATES;
import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES;
-import static com.android.server.power.stats.MobileRadioPowerStatsCollector.mapRadioAccessNetworkTypeToRadioAccessTechnology;
-
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -149,6 +147,7 @@
import com.android.server.LocalServices;
import com.android.server.power.optimization.Flags;
import com.android.server.power.stats.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
+import com.android.server.power.stats.format.MobileRadioPowerStatsLayout;
import libcore.util.EmptyArray;
@@ -180,7 +179,6 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
-import java.util.function.IntSupplier;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
@@ -2028,7 +2026,7 @@
void setContext(Context context) {
mPackageManager = context.getPackageManager();
mConsumedEnergyRetriever = new PowerStatsCollector.ConsumedEnergyRetrieverImpl(
- LocalServices.getService(PowerStatsInternal.class));
+ LocalServices.getService(PowerStatsInternal.class), () -> mBatteryVoltageMv);
mNetworkStatsManager = context.getSystemService(NetworkStatsManager.class);
mTelephonyManager =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
@@ -2083,11 +2081,6 @@
}
@Override
- public IntSupplier getVoltageSupplier() {
- return () -> mBatteryVoltageMv;
- }
-
- @Override
public ScreenPowerStatsCollector.ScreenUsageTimeRetriever getScreenUsageTimeRetriever() {
return mScreenUsageTimeRetriever;
}
@@ -13191,7 +13184,8 @@
final int freq = deltaInfo.getSpecificInfoFrequencyRange(index);
// Map RadioAccessNetworkType to course grain RadioAccessTechnology.
- final int ratBucket = mapRadioAccessNetworkTypeToRadioAccessTechnology(rat);
+ final int ratBucket = MobileRadioPowerStatsLayout
+ .mapRadioAccessNetworkTypeToRadioAccessTechnology(rat);
final RadioAccessTechnologyBatteryStats ratStats = getRatBatteryStatsLocked(
ratBucket);
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 d51cfea..87a3e5e 100644
--- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
+++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
@@ -16,6 +16,7 @@
package com.android.server.power.stats;
+import android.annotation.NonNull;
import android.content.Context;
import android.hardware.SensorManager;
import android.os.BatteryConsumer;
@@ -27,7 +28,6 @@
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
-import android.util.SparseBooleanArray;
import com.android.internal.os.Clock;
import com.android.internal.os.CpuScalingPolicies;
@@ -44,8 +44,7 @@
public class BatteryUsageStatsProvider {
private static final String TAG = "BatteryUsageStatsProv";
private final Context mContext;
- private final SparseBooleanArray mPowerStatsExporterEnabled = new SparseBooleanArray();
- private final PowerStatsExporter mPowerStatsExporter;
+ private final PowerAttributor mPowerAttributor;
private final PowerStatsStore mPowerStatsStore;
private final PowerProfile mPowerProfile;
private final CpuScalingPolicies mCpuScalingPolicies;
@@ -53,16 +52,18 @@
private final Object mLock = new Object();
private List<PowerCalculator> mPowerCalculators;
- public BatteryUsageStatsProvider(Context context,
- PowerStatsExporter powerStatsExporter,
- PowerProfile powerProfile, CpuScalingPolicies cpuScalingPolicies,
- PowerStatsStore powerStatsStore, Clock clock) {
+ public BatteryUsageStatsProvider(@NonNull Context context,
+ @NonNull PowerAttributor powerAttributor,
+ @NonNull PowerProfile powerProfile, @NonNull CpuScalingPolicies cpuScalingPolicies,
+ @NonNull PowerStatsStore powerStatsStore, @NonNull Clock clock) {
mContext = context;
- mPowerStatsExporter = powerStatsExporter;
+ mPowerAttributor = powerAttributor;
mPowerStatsStore = powerStatsStore;
mPowerProfile = powerProfile;
mCpuScalingPolicies = cpuScalingPolicies;
mClock = clock;
+
+ mPowerStatsStore.addSectionReader(new BatteryUsageStatsSection.Reader());
}
private List<PowerCalculator> getPowerCalculators() {
@@ -72,55 +73,67 @@
// Power calculators are applied in the order of registration
mPowerCalculators.add(new BatteryChargeCalculator());
- if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_CPU)) {
+ if (!mPowerAttributor.isPowerComponentSupported(
+ BatteryConsumer.POWER_COMPONENT_CPU)) {
mPowerCalculators.add(
new CpuPowerCalculator(mCpuScalingPolicies, mPowerProfile));
}
mPowerCalculators.add(new MemoryPowerCalculator(mPowerProfile));
mPowerCalculators.add(new WakelockPowerCalculator(mPowerProfile));
if (!BatteryStats.checkWifiOnly(mContext)) {
- if (!mPowerStatsExporterEnabled.get(
+ if (!mPowerAttributor.isPowerComponentSupported(
BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) {
mPowerCalculators.add(new MobileRadioPowerCalculator(mPowerProfile));
}
- if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_PHONE)) {
+ if (!mPowerAttributor.isPowerComponentSupported(
+ BatteryConsumer.POWER_COMPONENT_PHONE)) {
mPowerCalculators.add(new PhonePowerCalculator(mPowerProfile));
}
}
- if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_WIFI)) {
+ if (!mPowerAttributor.isPowerComponentSupported(
+ BatteryConsumer.POWER_COMPONENT_WIFI)) {
mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile));
}
- if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_BLUETOOTH)) {
+ if (!mPowerAttributor.isPowerComponentSupported(
+ BatteryConsumer.POWER_COMPONENT_BLUETOOTH)) {
mPowerCalculators.add(new BluetoothPowerCalculator(mPowerProfile));
}
- if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_SENSORS)) {
+ if (!mPowerAttributor.isPowerComponentSupported(
+ BatteryConsumer.POWER_COMPONENT_SENSORS)) {
mPowerCalculators.add(new SensorPowerCalculator(
mContext.getSystemService(SensorManager.class)));
}
- if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_GNSS)) {
+ if (!mPowerAttributor.isPowerComponentSupported(
+ BatteryConsumer.POWER_COMPONENT_GNSS)) {
mPowerCalculators.add(new GnssPowerCalculator(mPowerProfile));
}
- if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_CAMERA)) {
+ if (!mPowerAttributor.isPowerComponentSupported(
+ BatteryConsumer.POWER_COMPONENT_CAMERA)) {
mPowerCalculators.add(new CameraPowerCalculator(mPowerProfile));
}
- if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT)) {
+ if (!mPowerAttributor.isPowerComponentSupported(
+ BatteryConsumer.POWER_COMPONENT_FLASHLIGHT)) {
mPowerCalculators.add(new FlashlightPowerCalculator(mPowerProfile));
}
- if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_AUDIO)) {
+ if (!mPowerAttributor.isPowerComponentSupported(
+ BatteryConsumer.POWER_COMPONENT_AUDIO)) {
mPowerCalculators.add(new AudioPowerCalculator(mPowerProfile));
}
- if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_VIDEO)) {
+ if (!mPowerAttributor.isPowerComponentSupported(
+ BatteryConsumer.POWER_COMPONENT_VIDEO)) {
mPowerCalculators.add(new VideoPowerCalculator(mPowerProfile));
}
- if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_SCREEN)) {
+ if (!mPowerAttributor.isPowerComponentSupported(
+ BatteryConsumer.POWER_COMPONENT_SCREEN)) {
mPowerCalculators.add(new ScreenPowerCalculator(mPowerProfile));
}
- if (!mPowerStatsExporterEnabled.get(
+ if (!mPowerAttributor.isPowerComponentSupported(
BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY)) {
mPowerCalculators.add(new AmbientDisplayPowerCalculator(mPowerProfile));
}
mPowerCalculators.add(new IdlePowerCalculator(mPowerProfile));
- if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_ANY)) {
+ if (!mPowerAttributor.isPowerComponentSupported(
+ BatteryConsumer.POWER_COMPONENT_ANY)) {
mPowerCalculators.add(new CustomEnergyConsumerPowerCalculator(mPowerProfile));
}
mPowerCalculators.add(new UserPowerCalculator());
@@ -196,7 +209,7 @@
final boolean includeProcessStateData = ((query.getFlags()
& BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_PROCESS_STATE_DATA) != 0)
&& stats.isProcessStateDataAvailable();
- final boolean includeVirtualUids = ((query.getFlags()
+ final boolean includeVirtualUids = ((query.getFlags()
& BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_VIRTUAL_UIDS) != 0);
final double minConsumedPowerThreshold = query.getMinConsumedPowerThreshold();
@@ -258,10 +271,8 @@
}
}
- if (mPowerStatsExporterEnabled.indexOfValue(true) >= 0) {
- mPowerStatsExporter.exportAggregatedPowerStats(batteryUsageStatsBuilder,
- monotonicStartTime, monotonicEndTime);
- }
+ mPowerAttributor.estimatePowerConsumption(batteryUsageStatsBuilder, stats.getHistory(),
+ monotonicStartTime, monotonicEndTime);
BatteryUsageStats batteryUsageStats = batteryUsageStatsBuilder.build();
if (includeProcessStateData) {
@@ -272,6 +283,7 @@
// STOPSHIP(b/229906525): remove verification before shipping
private static boolean sErrorReported;
+
private void verify(BatteryUsageStats stats) {
if (sErrorReported) {
return;
@@ -390,7 +402,7 @@
// while the "to" timestamp is *inclusive*.
boolean isInRange =
(query.getFromTimestamp() == 0 || minTime > query.getFromTimestamp())
- && (query.getToTimestamp() == 0 || maxTime <= query.getToTimestamp());
+ && (query.getToTimestamp() == 0 || maxTime <= query.getToTimestamp());
if (!isInRange) {
continue;
}
@@ -422,12 +434,4 @@
}
return builder.build();
}
-
- /**
- * Specify whether PowerStats based attribution is supported for the specified component.
- */
- public void setPowerStatsExporterEnabled(int powerComponentId, boolean enabled) {
- mPowerStatsExporterEnabled.put(powerComponentId, enabled);
- mPowerStatsExporter.setPowerComponentEnabled(powerComponentId, enabled);
- }
}
diff --git a/services/core/java/com/android/server/power/stats/BatteryUsageStatsSection.java b/services/core/java/com/android/server/power/stats/BatteryUsageStatsSection.java
index b95faac..af36524 100644
--- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsSection.java
+++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsSection.java
@@ -19,8 +19,11 @@
import android.os.BatteryUsageStats;
import android.util.IndentingPrintWriter;
+import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
class BatteryUsageStatsSection extends PowerStatsSpan.Section {
@@ -38,7 +41,7 @@
}
@Override
- void write(TypedXmlSerializer serializer) throws IOException {
+ public void write(TypedXmlSerializer serializer) throws IOException {
mBatteryUsageStats.writeXml(serializer);
}
@@ -46,4 +49,17 @@
public void dump(IndentingPrintWriter ipw) {
mBatteryUsageStats.dump(ipw, "");
}
+
+ static class Reader implements PowerStatsSpan.SectionReader {
+ @Override
+ public String getType() {
+ return TYPE;
+ }
+
+ @Override
+ public PowerStatsSpan.Section read(String sectionType, TypedXmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ return new BatteryUsageStatsSection(BatteryUsageStats.createFromXml(parser));
+ }
+ }
}
diff --git a/services/core/java/com/android/server/power/stats/BluetoothPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/BluetoothPowerStatsCollector.java
index 8a5085b..539c415 100644
--- a/services/core/java/com/android/server/power/stats/BluetoothPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/BluetoothPowerStatsCollector.java
@@ -28,13 +28,12 @@
import com.android.internal.os.Clock;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.BluetoothPowerStatsLayout;
-import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
-import java.util.function.IntSupplier;
public class BluetoothPowerStatsCollector extends PowerStatsCollector {
private static final String TAG = "BluetoothPowerStatsCollector";
@@ -43,7 +42,7 @@
private static final long ENERGY_UNSPECIFIED = -1;
- interface BluetoothStatsRetriever {
+ public interface BluetoothStatsRetriever {
interface Callback {
void onBluetoothScanTime(int uid, long scanTimeMs);
}
@@ -54,29 +53,25 @@
BluetoothAdapter.OnBluetoothActivityEnergyInfoCallback callback);
}
- interface Injector {
+ public interface Injector {
Handler getHandler();
Clock getClock();
PowerStatsUidResolver getUidResolver();
long getPowerStatsCollectionThrottlePeriod(String powerComponentName);
PackageManager getPackageManager();
ConsumedEnergyRetriever getConsumedEnergyRetriever();
- IntSupplier getVoltageSupplier();
BluetoothStatsRetriever getBluetoothStatsRetriever();
}
private final Injector mInjector;
- private BluetoothPowerStatsLayout mLayout;
+ private com.android.server.power.stats.format.BluetoothPowerStatsLayout mLayout;
private boolean mIsInitialized;
private PowerStats mPowerStats;
private long[] mDeviceStats;
private BluetoothStatsRetriever mBluetoothStatsRetriever;
private ConsumedEnergyRetriever mConsumedEnergyRetriever;
- private IntSupplier mVoltageSupplier;
- private int[] mEnergyConsumerIds = new int[0];
- private long[] mLastConsumedEnergyUws;
- private int mLastVoltageMv;
+ private ConsumedEnergyHelper mConsumedEnergyHelper;
private long mLastRxTime;
private long mLastTxTime;
@@ -93,7 +88,7 @@
private final SparseArray<UidStats> mUidStats = new SparseArray<>();
- BluetoothPowerStatsCollector(Injector injector) {
+ public BluetoothPowerStatsCollector(Injector injector) {
super(injector.getHandler(), injector.getPowerStatsCollectionThrottlePeriod(
BatteryConsumer.powerComponentIdToString(
BatteryConsumer.POWER_COMPONENT_BLUETOOTH)),
@@ -122,21 +117,11 @@
return false;
}
- mConsumedEnergyRetriever = mInjector.getConsumedEnergyRetriever();
- mVoltageSupplier = mInjector.getVoltageSupplier();
mBluetoothStatsRetriever = mInjector.getBluetoothStatsRetriever();
- mEnergyConsumerIds =
- mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.BLUETOOTH);
- mLastConsumedEnergyUws = new long[mEnergyConsumerIds.length];
- Arrays.fill(mLastConsumedEnergyUws, ENERGY_UNSPECIFIED);
-
- mLayout = new BluetoothPowerStatsLayout();
- mLayout.addDeviceBluetoothControllerActivity();
- mLayout.addDeviceSectionEnergyConsumers(mEnergyConsumerIds.length);
- mLayout.addDeviceSectionUsageDuration();
- mLayout.addDeviceSectionPowerEstimate();
- mLayout.addUidTrafficStats();
- mLayout.addUidSectionPowerEstimate();
+ mConsumedEnergyRetriever = mInjector.getConsumedEnergyRetriever();
+ mConsumedEnergyHelper = new ConsumedEnergyHelper(mConsumedEnergyRetriever,
+ EnergyConsumerType.BLUETOOTH);
+ mLayout = new BluetoothPowerStatsLayout(mConsumedEnergyHelper.getEnergyConsumerCount());
PersistableBundle extras = new PersistableBundle();
mLayout.toExtras(extras);
@@ -152,7 +137,7 @@
}
@Override
- protected PowerStats collectStats() {
+ public PowerStats collectStats() {
if (!ensureInitialized()) {
return null;
}
@@ -162,9 +147,7 @@
collectBluetoothActivityInfo();
collectBluetoothScanStats();
- if (mEnergyConsumerIds.length != 0) {
- collectEnergyConsumers();
- }
+ mConsumedEnergyHelper.collectConsumedEnergy(mPowerStats, mLayout);
return mPowerStats;
}
@@ -296,34 +279,6 @@
mLayout.setDeviceScanTime(mDeviceStats, totalScanTime);
}
- 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);
diff --git a/services/core/java/com/android/server/power/stats/CameraPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/CameraPowerStatsCollector.java
index 8705bd5..0f70064 100644
--- a/services/core/java/com/android/server/power/stats/CameraPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/CameraPowerStatsCollector.java
@@ -19,12 +19,13 @@
import android.hardware.power.stats.EnergyConsumerType;
import android.os.BatteryConsumer;
+import com.android.server.power.stats.format.BinaryStatePowerStatsLayout;
+
public class CameraPowerStatsCollector extends EnergyConsumerPowerStatsCollector {
- CameraPowerStatsCollector(Injector injector) {
+ public CameraPowerStatsCollector(Injector injector) {
super(injector, BatteryConsumer.POWER_COMPONENT_CAMERA,
BatteryConsumer.powerComponentIdToString(BatteryConsumer.POWER_COMPONENT_CAMERA),
- EnergyConsumerType.CAMERA, /* energy consumer name */ null,
- new BinaryStatePowerStatsLayout());
+ EnergyConsumerType.CAMERA, new BinaryStatePowerStatsLayout());
}
}
diff --git a/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java
index b5ef67b..128f14a 100644
--- a/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/CpuPowerStatsCollector.java
@@ -31,11 +31,10 @@
import com.android.internal.os.CpuScalingPolicies;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.CpuPowerStatsLayout;
import java.io.PrintWriter;
-import java.util.Arrays;
import java.util.Locale;
-import java.util.function.IntSupplier;
/**
* Collects snapshots of power-related system statistics.
@@ -46,7 +45,6 @@
public class CpuPowerStatsCollector extends PowerStatsCollector {
private static final String TAG = "CpuPowerStatsCollector";
private static final long NANOS_PER_MILLIS = 1000000;
- private static final long ENERGY_UNSPECIFIED = -1;
private static final int DEFAULT_CPU_POWER_BRACKETS = 3;
private static final int DEFAULT_CPU_POWER_BRACKETS_PER_ENERGY_CONSUMER = 2;
@@ -58,7 +56,6 @@
PowerProfile getPowerProfile();
KernelCpuStatsReader getKernelCpuStatsReader();
ConsumedEnergyRetriever getConsumedEnergyRetriever();
- IntSupplier getVoltageSupplier();
long getPowerStatsCollectionThrottlePeriod(String powerComponentName);
default int getDefaultCpuPowerBrackets() {
@@ -76,8 +73,7 @@
private CpuScalingPolicies mCpuScalingPolicies;
private PowerProfile mPowerProfile;
private KernelCpuStatsReader mKernelCpuStatsReader;
- private ConsumedEnergyRetriever mConsumedEnergyRetriever;
- private IntSupplier mVoltageSupplier;
+ private ConsumedEnergyHelper mConsumedEnergyHelper;
private int mDefaultCpuPowerBrackets;
private int mDefaultCpuPowerBracketsPerEnergyConsumer;
private long[] mCpuTimeByScalingStep;
@@ -85,15 +81,12 @@
private long[] mTempUidStats;
private final SparseArray<UidStats> mUidStats = new SparseArray<>();
private boolean mIsPerUidTimeInStateSupported;
- private int[] mCpuEnergyConsumerIds = new int[0];
private PowerStats.Descriptor mPowerStatsDescriptor;
// Reusable instance
private PowerStats mCpuPowerStats;
private CpuPowerStatsLayout mLayout;
private long mLastUpdateTimestampNanos;
private long mLastUpdateUptimeMillis;
- private int mLastVoltageMv;
- private long[] mLastConsumedEnergyUws;
CpuPowerStatsCollector(Injector injector) {
super(injector.getHandler(), injector.getPowerStatsCollectionThrottlePeriod(
@@ -115,31 +108,22 @@
mCpuScalingPolicies = mInjector.getCpuScalingPolicies();
mPowerProfile = mInjector.getPowerProfile();
mKernelCpuStatsReader = mInjector.getKernelCpuStatsReader();
- mConsumedEnergyRetriever = mInjector.getConsumedEnergyRetriever();
- mVoltageSupplier = mInjector.getVoltageSupplier();
mDefaultCpuPowerBrackets = mInjector.getDefaultCpuPowerBrackets();
mDefaultCpuPowerBracketsPerEnergyConsumer =
mInjector.getDefaultCpuPowerBracketsPerEnergyConsumer();
mIsPerUidTimeInStateSupported = mKernelCpuStatsReader.isSupportedFeature();
- mCpuEnergyConsumerIds =
- mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.CPU_CLUSTER);
- mLastConsumedEnergyUws = new long[mCpuEnergyConsumerIds.length];
- Arrays.fill(mLastConsumedEnergyUws, ENERGY_UNSPECIFIED);
+
+ mConsumedEnergyHelper = new ConsumedEnergyHelper(mInjector.getConsumedEnergyRetriever(),
+ EnergyConsumerType.CPU_CLUSTER);
int cpuScalingStepCount = mCpuScalingPolicies.getScalingStepCount();
mCpuTimeByScalingStep = new long[cpuScalingStepCount];
mTempCpuTimeByScalingStep = new long[cpuScalingStepCount];
int[] scalingStepToPowerBracketMap = initPowerBrackets();
- mLayout = new CpuPowerStatsLayout();
- mLayout.addDeviceSectionCpuTimeByScalingStep(cpuScalingStepCount);
- mLayout.addDeviceSectionCpuTimeByCluster(mCpuScalingPolicies.getPolicies().length);
- mLayout.addDeviceSectionUsageDuration();
- mLayout.addDeviceSectionEnergyConsumers(mCpuEnergyConsumerIds.length);
- mLayout.addDeviceSectionPowerEstimate();
- mLayout.addUidSectionCpuTimeByPowerBracket(scalingStepToPowerBracketMap);
- mLayout.addUidSectionPowerEstimate();
+ mLayout = new CpuPowerStatsLayout(mConsumedEnergyHelper.getEnergyConsumerCount(),
+ mCpuScalingPolicies.getPolicies().length, scalingStepToPowerBracketMap);
PersistableBundle extras = new PersistableBundle();
mLayout.toExtras(extras);
@@ -158,16 +142,18 @@
private int[] initPowerBrackets() {
if (mPowerProfile.getCpuPowerBracketCount() != PowerProfile.POWER_BRACKETS_UNSPECIFIED) {
return initPowerBracketsFromPowerProfile();
- } else if (mCpuEnergyConsumerIds.length == 0 || mCpuEnergyConsumerIds.length == 1) {
+ } else if (mConsumedEnergyHelper.getEnergyConsumerCount() == 0
+ || mConsumedEnergyHelper.getEnergyConsumerCount() == 1) {
return initDefaultPowerBrackets(mDefaultCpuPowerBrackets);
- } else if (mCpuScalingPolicies.getPolicies().length == mCpuEnergyConsumerIds.length) {
+ } else if (mCpuScalingPolicies.getPolicies().length
+ == mConsumedEnergyHelper.getEnergyConsumerCount()) {
return initPowerBracketsByCluster(mDefaultCpuPowerBracketsPerEnergyConsumer);
} else {
Slog.i(TAG, "Assigning a single power brackets to each CPU_CLUSTER energy consumer."
+ " Number of CPU clusters ("
+ mCpuScalingPolicies.getPolicies().length
+ ") does not match the number of energy consumers ("
- + mCpuEnergyConsumerIds.length + "). "
+ + mConsumedEnergyHelper.getEnergyConsumerCount() + "). "
+ " Using default power bucket assignment.");
return initDefaultPowerBrackets(mDefaultCpuPowerBrackets);
}
@@ -368,41 +354,11 @@
}
mLayout.setUsageDuration(mCpuPowerStats.stats, uptimeDelta);
- if (mCpuEnergyConsumerIds.length != 0) {
- collectEnergyConsumers();
- }
+ mConsumedEnergyHelper.collectConsumedEnergy(mCpuPowerStats, mLayout);
return mCpuPowerStats;
}
- 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(mCpuEnergyConsumerIds);
- 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(mCpuPowerStats.stats, i, uJtoUc(energyDelta, averageVoltage));
- mLastConsumedEnergyUws[i] = energyUws[i];
- }
- }
-
@VisibleForNative
interface KernelCpuStatsCallback {
@Keep // Called from native
diff --git a/services/core/java/com/android/server/power/stats/CustomEnergyConsumerPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/CustomEnergyConsumerPowerStatsCollector.java
index 4bfe442..c1c7e12 100644
--- a/services/core/java/com/android/server/power/stats/CustomEnergyConsumerPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/CustomEnergyConsumerPowerStatsCollector.java
@@ -19,6 +19,8 @@
import android.hardware.power.stats.EnergyConsumerType;
import android.os.BatteryConsumer;
+import com.android.server.power.stats.format.EnergyConsumerPowerStatsLayout;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -29,7 +31,8 @@
private final EnergyConsumerPowerStatsCollector.Injector mInjector;
private List<EnergyConsumerPowerStatsCollector> mCollectors;
- CustomEnergyConsumerPowerStatsCollector(EnergyConsumerPowerStatsCollector.Injector injector) {
+ public CustomEnergyConsumerPowerStatsCollector(
+ EnergyConsumerPowerStatsCollector.Injector injector) {
super(injector.getHandler(), 0, injector.getUidResolver(), injector.getClock());
mInjector = injector;
}
@@ -46,7 +49,8 @@
for (int i = 0; i < energyConsumerIds.length; i++) {
String name = retriever.getEnergyConsumerName(energyConsumerIds[i]);
EnergyConsumerPowerStatsCollector collector = new EnergyConsumerPowerStatsCollector(
- mInjector, powerComponentId++, name, energyConsumerIds[i], sLayout);
+ mInjector, powerComponentId++, name, EnergyConsumerType.OTHER,
+ energyConsumerIds[i], sLayout);
collector.setEnabled(true);
collector.addConsumer(this::deliverStats);
mCollectors.add(collector);
diff --git a/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsCollector.java
index 79fbe8e..1d2e388 100644
--- a/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsCollector.java
@@ -16,78 +16,57 @@
package com.android.server.power.stats;
-import android.hardware.power.stats.EnergyConsumerAttribution;
-import android.hardware.power.stats.EnergyConsumerResult;
import android.hardware.power.stats.EnergyConsumerType;
import android.os.Handler;
import android.os.PersistableBundle;
-import android.util.Slog;
-import android.util.SparseLongArray;
import com.android.internal.os.Clock;
import com.android.internal.os.PowerStats;
-
-import java.util.function.IntSupplier;
+import com.android.server.power.stats.format.EnergyConsumerPowerStatsLayout;
public class EnergyConsumerPowerStatsCollector extends PowerStatsCollector {
- private static final String TAG = "EnergyConsumerPowerStatsCollector";
- private static final long ENERGY_UNSPECIFIED = -1;
-
- interface Injector {
+ public interface Injector {
Handler getHandler();
Clock getClock();
PowerStatsUidResolver getUidResolver();
long getPowerStatsCollectionThrottlePeriod(String powerComponentName);
ConsumedEnergyRetriever getConsumedEnergyRetriever();
- IntSupplier getVoltageSupplier();
}
+ private static final int UNSPECIFIED = -1;
+
private final Injector mInjector;
private final int mPowerComponentId;
private final String mPowerComponentName;
+ private final int mEnergyConsumerId;
private final int mEnergyConsumerType;
- private final String mEnergyConsumerName;
private final EnergyConsumerPowerStatsLayout mLayout;
private boolean mIsInitialized;
private PowerStats mPowerStats;
- private ConsumedEnergyRetriever mConsumedEnergyRetriever;
- private IntSupplier mVoltageSupplier;
- private int[] mEnergyConsumerIds;
- private long mLastConsumedEnergyUws = ENERGY_UNSPECIFIED;
- private SparseLongArray mLastConsumerEnergyPerUid = new SparseLongArray();
- private int mLastVoltageMv;
+ private ConsumedEnergyHelper mConsumedEnergyHelper;
private long mLastUpdateTimestamp;
- private boolean mFirstCollection = true;
EnergyConsumerPowerStatsCollector(Injector injector, int powerComponentId,
String powerComponentName, @EnergyConsumerType int energyConsumerType,
- String energyConsumerName, EnergyConsumerPowerStatsLayout statsLayout) {
- super(injector.getHandler(),
- injector.getPowerStatsCollectionThrottlePeriod(powerComponentName),
- injector.getUidResolver(), injector.getClock());
- mInjector = injector;
- mPowerComponentId = powerComponentId;
- mPowerComponentName = powerComponentName;
- mEnergyConsumerType = energyConsumerType;
- mEnergyConsumerName = energyConsumerName;
- mLayout = statsLayout;
+ EnergyConsumerPowerStatsLayout statsLayout) {
+ this(injector, powerComponentId, powerComponentName, energyConsumerType, UNSPECIFIED,
+ statsLayout);
}
EnergyConsumerPowerStatsCollector(Injector injector, int powerComponentId,
- String powerComponentName, int energyConsumerId,
- EnergyConsumerPowerStatsLayout statsLayout) {
+ String powerComponentName, @EnergyConsumerType int energyConsumerType,
+ int energyConsumerId, EnergyConsumerPowerStatsLayout statsLayout) {
super(injector.getHandler(),
injector.getPowerStatsCollectionThrottlePeriod(powerComponentName),
injector.getUidResolver(), injector.getClock());
mInjector = injector;
mPowerComponentId = powerComponentId;
mPowerComponentName = powerComponentName;
- mEnergyConsumerIds = new int[]{energyConsumerId};
- mEnergyConsumerType = EnergyConsumerType.OTHER;
- mEnergyConsumerName = null;
+ mEnergyConsumerId = energyConsumerId;
+ mEnergyConsumerType = energyConsumerType;
mLayout = statsLayout;
}
@@ -100,12 +79,14 @@
return false;
}
- mConsumedEnergyRetriever = mInjector.getConsumedEnergyRetriever();
- mVoltageSupplier = mInjector.getVoltageSupplier();
- if (mEnergyConsumerIds == null) {
- mEnergyConsumerIds = mConsumedEnergyRetriever.getEnergyConsumerIds(mEnergyConsumerType,
- mEnergyConsumerName);
+ if (mEnergyConsumerId != UNSPECIFIED) {
+ mConsumedEnergyHelper = new ConsumedEnergyHelper(mInjector.getConsumedEnergyRetriever(),
+ mEnergyConsumerId, true /* perUidAttribution */);
+ } else {
+ mConsumedEnergyHelper = new ConsumedEnergyHelper(mInjector.getConsumedEnergyRetriever(),
+ mEnergyConsumerType);
}
+
PersistableBundle extras = new PersistableBundle();
mLayout.toExtras(extras);
PowerStats.Descriptor powerStatsDescriptor = new PowerStats.Descriptor(
@@ -124,85 +105,15 @@
return null;
}
- if (mEnergyConsumerIds.length == 0) {
- return null;
- }
-
- int voltageMv = mVoltageSupplier.getAsInt();
- int averageVoltage = mLastVoltageMv != 0 ? (mLastVoltageMv + voltageMv) / 2 : voltageMv;
- if (averageVoltage <= 0) {
- Slog.wtf(TAG, "Unexpected battery voltage (" + voltageMv
- + " mV) when querying energy consumers");
- return null;
- }
-
- mLastVoltageMv = voltageMv;
-
- EnergyConsumerResult[] energy =
- mConsumedEnergyRetriever.getConsumedEnergy(mEnergyConsumerIds);
- long consumedEnergy = 0;
- if (energy != null) {
- for (int i = energy.length - 1; i >= 0; i--) {
- if (energy[i].energyUWs != ENERGY_UNSPECIFIED) {
- consumedEnergy += energy[i].energyUWs;
- }
- }
- }
-
- long energyDelta = mLastConsumedEnergyUws != ENERGY_UNSPECIFIED
- ? consumedEnergy - mLastConsumedEnergyUws : 0;
- mLastConsumedEnergyUws = consumedEnergy;
- if (energyDelta < 0) {
- // Likely, restart of powerstats HAL
- energyDelta = 0;
- }
-
- if (energyDelta == 0 && !mFirstCollection) {
- return null;
- }
-
- mLayout.setConsumedEnergy(mPowerStats.stats, 0, uJtoUc(energyDelta, averageVoltage));
-
mPowerStats.uidStats.clear();
- if (energy != null) {
- for (int i = energy.length - 1; i >= 0; i--) {
- EnergyConsumerAttribution[] perUid = energy[i].attribution;
- if (perUid == null) {
- continue;
- }
- for (EnergyConsumerAttribution attribution : perUid) {
- int uid = mUidResolver.mapUid(attribution.uid);
- long lastEnergy = mLastConsumerEnergyPerUid.get(uid, ENERGY_UNSPECIFIED);
- mLastConsumerEnergyPerUid.put(uid, attribution.energyUWs);
- if (lastEnergy == ENERGY_UNSPECIFIED) {
- continue;
- }
- long deltaEnergy = attribution.energyUWs - lastEnergy;
- if (deltaEnergy <= 0) {
- continue;
- }
- long[] uidStats = mPowerStats.uidStats.get(uid);
- if (uidStats == null) {
- uidStats = new long[mLayout.getUidStatsArrayLength()];
- mPowerStats.uidStats.put(uid, uidStats);
- }
-
- mLayout.setUidConsumedEnergy(uidStats, 0,
- mLayout.getUidConsumedEnergy(uidStats, 0)
- + uJtoUc(deltaEnergy, averageVoltage));
- }
- }
+ if (!mConsumedEnergyHelper.collectConsumedEnergy(mPowerStats, mLayout)) {
+ return null;
}
+
long timestamp = mClock.elapsedRealtime();
mPowerStats.durationMs = timestamp - mLastUpdateTimestamp;
mLastUpdateTimestamp = timestamp;
- mFirstCollection = false;
return mPowerStats;
}
-
- @Override
- protected void onUidRemoved(int uid) {
- mLastConsumerEnergyPerUid.delete(uid);
- }
}
diff --git a/services/core/java/com/android/server/power/stats/GnssPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/GnssPowerStatsCollector.java
index 168a874..c1b4c31 100644
--- a/services/core/java/com/android/server/power/stats/GnssPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/GnssPowerStatsCollector.java
@@ -19,12 +19,13 @@
import android.hardware.power.stats.EnergyConsumerType;
import android.os.BatteryConsumer;
+import com.android.server.power.stats.format.GnssPowerStatsLayout;
+
public class GnssPowerStatsCollector extends EnergyConsumerPowerStatsCollector {
- GnssPowerStatsCollector(Injector injector) {
+ public GnssPowerStatsCollector(Injector injector) {
super(injector, BatteryConsumer.POWER_COMPONENT_GNSS,
BatteryConsumer.powerComponentIdToString(BatteryConsumer.POWER_COMPONENT_GNSS),
- EnergyConsumerType.GNSS, /* energy consumer name */ null,
- new GnssPowerStatsLayout());
+ EnergyConsumerType.GNSS, new GnssPowerStatsLayout());
}
}
diff --git a/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsCollector.java
index c88e1b0..cbd6fab 100644
--- a/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsCollector.java
@@ -35,12 +35,12 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.Clock;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.MobileRadioPowerStatsLayout;
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.LongSupplier;
import java.util.function.Supplier;
@@ -56,8 +56,6 @@
private static final long MODEM_ACTIVITY_REQUEST_TIMEOUT = 20000;
- private static final long ENERGY_UNSPECIFIED = -1;
-
@VisibleForTesting
@AccessNetworkConstants.RadioAccessNetworkType
static final int[] NETWORK_TYPES = {
@@ -77,14 +75,13 @@
long elapsedRealtimeMs, long uptimeMs);
}
- interface Injector {
+ public interface Injector {
Handler getHandler();
Clock getClock();
PowerStatsUidResolver getUidResolver();
long getPowerStatsCollectionThrottlePeriod(String powerComponentName);
PackageManager getPackageManager();
ConsumedEnergyRetriever getConsumedEnergyRetriever();
- IntSupplier getVoltageSupplier();
Supplier<NetworkStats> getMobileNetworkStatsSupplier();
TelephonyManager getTelephonyManager();
LongSupplier getCallDurationSupplier();
@@ -103,18 +100,14 @@
private LongSupplier mCallDurationSupplier;
private LongSupplier mScanDurationSupplier;
private volatile Supplier<NetworkStats> mNetworkStatsSupplier;
- private ConsumedEnergyRetriever mConsumedEnergyRetriever;
- private IntSupplier mVoltageSupplier;
- private int[] mEnergyConsumerIds = new int[0];
+ private ConsumedEnergyHelper mConsumedEnergyHelper;
private long mLastUpdateTimestampMillis;
private ModemActivityInfo mLastModemActivityInfo;
private NetworkStats mLastNetworkStats;
- private long[] mLastConsumedEnergyUws;
- private int mLastVoltageMv;
private long mLastCallDuration;
private long mLastScanDuration;
- MobileRadioPowerStatsCollector(Injector injector, Observer observer) {
+ public MobileRadioPowerStatsCollector(Injector injector, Observer observer) {
super(injector.getHandler(), injector.getPowerStatsCollectionThrottlePeriod(
BatteryConsumer.powerComponentIdToString(
BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)),
@@ -144,34 +137,22 @@
return false;
}
- mConsumedEnergyRetriever = mInjector.getConsumedEnergyRetriever();
- mVoltageSupplier = mInjector.getVoltageSupplier();
-
mTelephonyManager = mInjector.getTelephonyManager();
mNetworkStatsSupplier = mInjector.getMobileNetworkStatsSupplier();
mCallDurationSupplier = mInjector.getCallDurationSupplier();
mScanDurationSupplier = mInjector.getPhoneSignalScanDurationSupplier();
- mEnergyConsumerIds = mConsumedEnergyRetriever.getEnergyConsumerIds(
+ mConsumedEnergyHelper = new ConsumedEnergyHelper(mInjector.getConsumedEnergyRetriever(),
EnergyConsumerType.MOBILE_RADIO);
- mLastConsumedEnergyUws = new long[mEnergyConsumerIds.length];
- Arrays.fill(mLastConsumedEnergyUws, ENERGY_UNSPECIFIED);
- mLayout = new MobileRadioPowerStatsLayout();
- mLayout.addDeviceMobileActivity();
- mLayout.addDeviceSectionEnergyConsumers(mEnergyConsumerIds.length);
- mLayout.addStateStats();
- mLayout.addUidNetworkStats();
- mLayout.addDeviceSectionUsageDuration();
- mLayout.addDeviceSectionPowerEstimate();
- mLayout.addUidSectionPowerEstimate();
+ mLayout = new MobileRadioPowerStatsLayout(mConsumedEnergyHelper.getEnergyConsumerCount());
SparseArray<String> stateLabels = new SparseArray<>();
for (int rat = 0; rat < BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
final int freqCount = rat == BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR
? ServiceState.FREQUENCY_RANGE_COUNT : 1;
for (int freq = 0; freq < freqCount; freq++) {
- int stateKey = makeStateKey(rat, freq);
+ int stateKey = MobileRadioPowerStatsLayout.makeStateKey(rat, freq);
StringBuilder sb = new StringBuilder();
if (rat != BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER) {
sb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
@@ -200,7 +181,7 @@
}
@Override
- protected PowerStats collectStats() {
+ public PowerStats collectStats() {
if (!ensureInitialized()) {
return null;
}
@@ -210,9 +191,8 @@
ModemActivityInfo modemActivityDelta = collectModemActivityInfo();
List<BatteryStatsImpl.NetworkStatsDelta> networkStatsDeltas = collectNetworkStats();
- if (mEnergyConsumerIds.length != 0) {
- collectEnergyConsumers();
- }
+
+ mConsumedEnergyHelper.collectConsumedEnergy(mPowerStats, mLayout);
if (mPowerStats.durationMs == 0) {
setTimestamp(mClock.elapsedRealtime());
@@ -346,65 +326,8 @@
return delta;
}
- 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];
- }
- }
-
- static int makeStateKey(int rat, int freqRange) {
- if (rat == BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR) {
- return rat | (freqRange << 8);
- } else {
- return rat;
- }
- }
-
private void setTimestamp(long timestamp) {
mPowerStats.durationMs = Math.max(timestamp - mLastUpdateTimestampMillis, 0);
mLastUpdateTimestampMillis = timestamp;
}
-
- @BatteryStats.RadioAccessTechnology
- static int mapRadioAccessNetworkTypeToRadioAccessTechnology(
- @AccessNetworkConstants.RadioAccessNetworkType int networkType) {
- switch (networkType) {
- case AccessNetworkConstants.AccessNetworkType.NGRAN:
- return BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR;
- case AccessNetworkConstants.AccessNetworkType.EUTRAN:
- return BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE;
- case AccessNetworkConstants.AccessNetworkType.UNKNOWN: //fallthrough
- case AccessNetworkConstants.AccessNetworkType.GERAN: //fallthrough
- case AccessNetworkConstants.AccessNetworkType.UTRAN: //fallthrough
- case AccessNetworkConstants.AccessNetworkType.CDMA2000: //fallthrough
- case AccessNetworkConstants.AccessNetworkType.IWLAN:
- return BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
- default:
- Slog.w(TAG,
- "Unhandled RadioAccessNetworkType (" + networkType + "), mapping to OTHER");
- return BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
- }
- }
}
diff --git a/services/core/java/com/android/server/power/stats/PowerAttributor.java b/services/core/java/com/android/server/power/stats/PowerAttributor.java
new file mode 100644
index 0000000..d1f8564
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/PowerAttributor.java
@@ -0,0 +1,59 @@
+/*
+ * 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.os.BatteryConsumer;
+import android.os.BatteryUsageStats;
+import android.util.IndentingPrintWriter;
+
+import com.android.internal.os.BatteryStatsHistory;
+
+public interface PowerAttributor {
+
+ /**
+ * Returns true if the specified power component can be handled by this PowerAttributor
+ */
+ boolean isPowerComponentSupported(@BatteryConsumer.PowerComponentId int powerComponentId);
+
+ /**
+ * Performs the power attribution calculations and returns the results by populating the
+ * supplied BatteryUsageStats.Builder
+ */
+ void estimatePowerConsumption(BatteryUsageStats.Builder batteryUsageStatsBuilder,
+ BatteryStatsHistory batteryHistory, long monotonicStartTime, long monotonicEndTime);
+
+ /**
+ * Computes estimated power consumption attribution for the specified time range and stores
+ * it in PowerStatsStore for potential accumulation.
+ *
+ * Returns the monotonic timestamp of the last processed history item.
+ */
+ long storeEstimatedPowerConsumption(BatteryStatsHistory batteryStatsHistory, long startTime,
+ long endTimeMs);
+
+ /**
+ * Returns the monotonic timestamp of the last processed history item, stored in
+ * PowerStatsStore.
+ */
+ long getLastSavedEstimatesPowerConsumptionTimestamp();
+
+ /**
+ * Performs the power attribution calculation and prints the results.
+ */
+ void dumpEstimatedPowerConsumption(IndentingPrintWriter ipw,
+ BatteryStatsHistory batteryStatsHistory, long startTime, long endTime);
+}
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsCollector.java b/services/core/java/com/android/server/power/stats/PowerStatsCollector.java
index f5b0005..291f0e3 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsCollector.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.power.stats.EnergyConsumer;
+import android.hardware.power.stats.EnergyConsumerAttribution;
import android.hardware.power.stats.EnergyConsumerResult;
import android.hardware.power.stats.EnergyConsumerType;
import android.os.ConditionVariable;
@@ -26,13 +27,16 @@
import android.power.PowerStatsInternal;
import android.util.IndentingPrintWriter;
import android.util.Slog;
+import android.util.SparseLongArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.Clock;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.PowerStatsLayout;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@@ -41,6 +45,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
+import java.util.function.IntSupplier;
/**
* Collects snapshots of power-related system statistics.
@@ -53,6 +58,8 @@
private static final String TAG = "PowerStatsCollector";
private static final int MILLIVOLTS_PER_VOLT = 1000;
private static final long POWER_STATS_ENERGY_CONSUMERS_TIMEOUT = 20000;
+ private static final long ENERGY_UNSPECIFIED = -1;
+
private final Handler mHandler;
protected final PowerStatsUidResolver mUidResolver;
protected final Clock mClock;
@@ -235,46 +242,31 @@
return (deltaEnergyUj * MILLIVOLTS_PER_VOLT + (avgVoltageMv / 2)) / avgVoltageMv;
}
- interface ConsumedEnergyRetriever {
+ public interface ConsumedEnergyRetriever {
+
@NonNull
- int[] getEnergyConsumerIds(@EnergyConsumerType int energyConsumerType, String name);
+ int[] getEnergyConsumerIds(@EnergyConsumerType int energyConsumerType);
String getEnergyConsumerName(int energyConsumerId);
@Nullable
EnergyConsumerResult[] getConsumedEnergy(int[] energyConsumerIds);
- @Nullable
- default long[] getConsumedEnergyUws(int[] energyConsumerIds) {
- EnergyConsumerResult[] results = getConsumedEnergy(energyConsumerIds);
- if (results == null) {
- return null;
- }
-
- long[] energy = new long[energyConsumerIds.length];
- for (int i = 0; i < energyConsumerIds.length; i++) {
- int id = energyConsumerIds[i];
- for (EnergyConsumerResult result : results) {
- if (result.id == id) {
- energy[i] = result.energyUWs;
- break;
- }
- }
- }
- return energy;
- }
-
- default int[] getEnergyConsumerIds(@EnergyConsumerType int energyConsumerType) {
- return getEnergyConsumerIds(energyConsumerType, null);
- }
+ /**
+ * Returns the last known battery/charger voltage in milli-volts.
+ */
+ int getVoltageMv();
}
static class ConsumedEnergyRetrieverImpl implements ConsumedEnergyRetriever {
private final PowerStatsInternal mPowerStatsInternal;
+ private final IntSupplier mVoltageSupplier;
private EnergyConsumer[] mEnergyConsumers;
- ConsumedEnergyRetrieverImpl(PowerStatsInternal powerStatsInternal) {
+ ConsumedEnergyRetrieverImpl(PowerStatsInternal powerStatsInternal,
+ IntSupplier voltageSupplier) {
mPowerStatsInternal = powerStatsInternal;
+ mVoltageSupplier = voltageSupplier;
}
private void ensureEnergyConsumers() {
@@ -293,8 +285,9 @@
}
}
+ @NonNull
@Override
- public int[] getEnergyConsumerIds(int energyConsumerType, String name) {
+ public int[] getEnergyConsumerIds(int energyConsumerType) {
ensureEnergyConsumers();
if (mEnergyConsumers.length == 0) {
@@ -303,8 +296,7 @@
List<EnergyConsumer> energyConsumers = new ArrayList<>();
for (EnergyConsumer energyConsumer : mEnergyConsumers) {
- if (energyConsumer.type == energyConsumerType
- && (name == null || name.equals(energyConsumer.name))) {
+ if (energyConsumer.type == energyConsumerType) {
energyConsumers.add(energyConsumer);
}
}
@@ -335,6 +327,11 @@
}
@Override
+ public int getVoltageMv() {
+ return mVoltageSupplier.getAsInt();
+ }
+
+ @Override
public String getEnergyConsumerName(int energyConsumerId) {
ensureEnergyConsumers();
@@ -368,4 +365,152 @@
return sb.toString();
}
}
+
+ class ConsumedEnergyHelper implements PowerStatsUidResolver.Listener {
+ private final ConsumedEnergyRetriever mConsumedEnergyRetriever;
+ private final @EnergyConsumerType int mEnergyConsumerType;
+ private final boolean mPerUidAttributionSupported;
+
+ private boolean mIsInitialized;
+ private boolean mFirstCollection = true;
+ private int[] mEnergyConsumerIds;
+ private long[] mLastConsumedEnergyUws;
+ private final SparseLongArray mLastConsumerEnergyPerUid;
+ private int mLastVoltageMv;
+
+ ConsumedEnergyHelper(ConsumedEnergyRetriever consumedEnergyRetriever,
+ @EnergyConsumerType int energyConsumerType) {
+ mConsumedEnergyRetriever = consumedEnergyRetriever;
+ mEnergyConsumerType = energyConsumerType;
+ mPerUidAttributionSupported = false;
+ mLastConsumerEnergyPerUid = null;
+ }
+
+ ConsumedEnergyHelper(ConsumedEnergyRetriever consumedEnergyRetriever,
+ int energyConsumerId, boolean perUidAttributionSupported) {
+ mConsumedEnergyRetriever = consumedEnergyRetriever;
+ mEnergyConsumerType = EnergyConsumerType.OTHER;
+ mEnergyConsumerIds = new int[]{energyConsumerId};
+ mPerUidAttributionSupported = perUidAttributionSupported;
+ mLastConsumerEnergyPerUid = mPerUidAttributionSupported ? new SparseLongArray() : null;
+ }
+
+ private void ensureInitialized() {
+ if (!mIsInitialized) {
+ if (mEnergyConsumerIds == null) {
+ mEnergyConsumerIds = mConsumedEnergyRetriever.getEnergyConsumerIds(
+ mEnergyConsumerType);
+ }
+ mLastConsumedEnergyUws = new long[mEnergyConsumerIds.length];
+ Arrays.fill(mLastConsumedEnergyUws, ENERGY_UNSPECIFIED);
+ mUidResolver.addListener(this);
+ mIsInitialized = true;
+ }
+ }
+
+ int getEnergyConsumerCount() {
+ ensureInitialized();
+ return mEnergyConsumerIds.length;
+ }
+
+ boolean collectConsumedEnergy(PowerStats powerStats, PowerStatsLayout layout) {
+ ensureInitialized();
+
+ if (mEnergyConsumerIds.length == 0) {
+ return false;
+ }
+
+ int voltageMv = mConsumedEnergyRetriever.getVoltageMv();
+ int averageVoltage = mLastVoltageMv != 0 ? (mLastVoltageMv + voltageMv) / 2 : voltageMv;
+ if (averageVoltage <= 0) {
+ Slog.wtf(TAG, "Unexpected battery voltage (" + voltageMv
+ + " mV) when querying energy consumers");
+ return false;
+ }
+
+ mLastVoltageMv = voltageMv;
+
+ EnergyConsumerResult[] energy =
+ mConsumedEnergyRetriever.getConsumedEnergy(mEnergyConsumerIds);
+ System.out.println("mEnergyConsumerIds = " + Arrays.toString(mEnergyConsumerIds) + " "
+ + "energy = "
+ + Arrays.toString(energy));
+ if (energy == null) {
+ return false;
+ }
+
+ for (int i = 0; i < mEnergyConsumerIds.length; i++) {
+ populatePowerStats(powerStats, layout, energy, i, averageVoltage);
+ }
+ mFirstCollection = false;
+ return true;
+ }
+
+ private void populatePowerStats(PowerStats powerStats, PowerStatsLayout layout,
+ @NonNull EnergyConsumerResult[] energy, int energyConsumerIndex,
+ int averageVoltage) {
+ long consumedEnergy = energy[energyConsumerIndex].energyUWs;
+ long energyDelta = mLastConsumedEnergyUws[energyConsumerIndex] != ENERGY_UNSPECIFIED
+ ? consumedEnergy - mLastConsumedEnergyUws[energyConsumerIndex] : 0;
+ mLastConsumedEnergyUws[energyConsumerIndex] = consumedEnergy;
+ if (energyDelta < 0) {
+ // Likely, restart of powerstats HAL
+ energyDelta = 0;
+ }
+
+ if (energyDelta == 0 && !mFirstCollection) {
+ return;
+ }
+
+ layout.setConsumedEnergy(powerStats.stats, energyConsumerIndex,
+ uJtoUc(energyDelta, averageVoltage));
+
+ if (!mPerUidAttributionSupported) {
+ return;
+ }
+
+ EnergyConsumerAttribution[] perUid = energy[energyConsumerIndex].attribution;
+ if (perUid == null) {
+ return;
+ }
+
+ for (EnergyConsumerAttribution attribution : perUid) {
+ int uid = mUidResolver.mapUid(attribution.uid);
+ long lastEnergy = mLastConsumerEnergyPerUid.get(uid, ENERGY_UNSPECIFIED);
+ mLastConsumerEnergyPerUid.put(uid, attribution.energyUWs);
+ if (lastEnergy == ENERGY_UNSPECIFIED) {
+ continue;
+ }
+ long deltaEnergy = attribution.energyUWs - lastEnergy;
+ if (deltaEnergy <= 0) {
+ continue;
+ }
+
+ long[] uidStats = powerStats.uidStats.get(uid);
+ if (uidStats == null) {
+ uidStats = new long[layout.getUidStatsArrayLength()];
+ powerStats.uidStats.put(uid, uidStats);
+ }
+
+ layout.setUidConsumedEnergy(uidStats, energyConsumerIndex,
+ layout.getUidConsumedEnergy(uidStats, energyConsumerIndex)
+ + uJtoUc(deltaEnergy, averageVoltage));
+ }
+ }
+
+ @Override
+ public void onAfterIsolatedUidRemoved(int isolatedUid, int parentUid) {
+ if (mLastConsumerEnergyPerUid != null) {
+ mHandler.post(() -> mLastConsumerEnergyPerUid.delete(isolatedUid));
+ }
+ }
+
+ @Override
+ public void onIsolatedUidAdded(int isolatedUid, int parentUid) {
+ }
+
+ @Override
+ public void onBeforeIsolatedUidRemoved(int isolatedUid, int parentUid) {
+ }
+ }
}
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsScheduler.java b/services/core/java/com/android/server/power/stats/PowerStatsScheduler.java
index abe4c0c..38ca087 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsScheduler.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsScheduler.java
@@ -23,6 +23,7 @@
import android.util.IndentingPrintWriter;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BatteryStatsHistory;
import com.android.internal.os.Clock;
import com.android.internal.os.MonotonicClock;
@@ -51,7 +52,8 @@
private final Handler mHandler;
private final Runnable mPowerStatsCollector;
private final Supplier<Long> mEarliestAvailableBatteryHistoryTimeMs;
- private final PowerStatsAggregator mPowerStatsAggregator;
+ private final BatteryStatsHistory mBatteryStatsHistory;
+ private final PowerAttributor mPowerAttributor;
private long mLastSavedSpanEndMonotonicTime;
/**
@@ -66,12 +68,13 @@
}
public PowerStatsScheduler(Runnable powerStatsCollector,
- PowerStatsAggregator powerStatsAggregator,
+ BatteryStatsHistory batteryStatsHistory, PowerAttributor powerAttributor,
@DurationMillisLong long aggregatedPowerStatsSpanDuration,
@DurationMillisLong long powerStatsAggregationPeriod, PowerStatsStore powerStatsStore,
AlarmScheduler alarmScheduler, Clock clock, MonotonicClock monotonicClock,
Supplier<Long> earliestAvailableBatteryHistoryTimeMs, Handler handler) {
- mPowerStatsAggregator = powerStatsAggregator;
+ mBatteryStatsHistory = batteryStatsHistory;
+ mPowerAttributor = powerAttributor;
mAggregatedPowerStatsSpanDuration = aggregatedPowerStatsSpanDuration;
mPowerStatsAggregationPeriod = powerStatsAggregationPeriod;
mPowerStatsStore = powerStatsStore;
@@ -123,12 +126,8 @@
long endTimeMs = alignToWallClock(startTime + mAggregatedPowerStatsSpanDuration,
mAggregatedPowerStatsSpanDuration, currentMonotonicTime, currentTimeMillis);
while (endTimeMs <= currentMonotonicTime) {
- mPowerStatsAggregator.aggregatePowerStats(startTime, endTimeMs,
- stats -> {
- storeAggregatedPowerStats(stats);
- mLastSavedSpanEndMonotonicTime = stats.getStartTime() + stats.getDuration();
- });
-
+ mLastSavedSpanEndMonotonicTime = mPowerAttributor.storeEstimatedPowerConsumption(
+ mBatteryStatsHistory, startTime, endTimeMs);
startTime = endTimeMs;
endTimeMs += mAggregatedPowerStatsSpanDuration;
}
@@ -153,15 +152,8 @@
mPowerStatsStore.dump(ipw);
// Aggregate the remainder of power stats and dump the results without storing them yet.
long powerStoreEndMonotonicTime = getLastSavedSpanEndMonotonicTime();
- mPowerStatsAggregator.aggregatePowerStats(powerStoreEndMonotonicTime,
- MonotonicClock.UNDEFINED,
- stats -> {
- // Create a PowerStatsSpan for consistency of the textual output
- PowerStatsSpan span = PowerStatsStore.createPowerStatsSpan(stats);
- if (span != null) {
- span.dump(ipw);
- }
- });
+ mPowerAttributor.dumpEstimatedPowerConsumption(ipw, mBatteryStatsHistory,
+ powerStoreEndMonotonicTime, MonotonicClock.UNDEFINED);
});
awaitCompletion();
@@ -223,28 +215,13 @@
}
private long getLastSavedSpanEndMonotonicTime() {
- if (mLastSavedSpanEndMonotonicTime != 0) {
- return mLastSavedSpanEndMonotonicTime;
- }
-
- mLastSavedSpanEndMonotonicTime = -1;
- for (PowerStatsSpan.Metadata metadata : mPowerStatsStore.getTableOfContents()) {
- if (metadata.getSections().contains(AggregatedPowerStatsSection.TYPE)) {
- for (PowerStatsSpan.TimeFrame timeFrame : metadata.getTimeFrames()) {
- long endMonotonicTime = timeFrame.startMonotonicTime + timeFrame.duration;
- if (endMonotonicTime > mLastSavedSpanEndMonotonicTime) {
- mLastSavedSpanEndMonotonicTime = endMonotonicTime;
- }
- }
- }
+ if (mLastSavedSpanEndMonotonicTime == 0) {
+ mLastSavedSpanEndMonotonicTime =
+ mPowerAttributor.getLastSavedEstimatesPowerConsumptionTimestamp();
}
return mLastSavedSpanEndMonotonicTime;
}
- private void storeAggregatedPowerStats(AggregatedPowerStats stats) {
- mPowerStatsStore.storeAggregatedPowerStats(stats);
- }
-
private void awaitCompletion() {
ConditionVariable done = new ConditionVariable();
mHandler.post(done::open);
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsSpan.java b/services/core/java/com/android/server/power/stats/PowerStatsSpan.java
index 4df919d..fc0611f 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsSpan.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsSpan.java
@@ -44,6 +44,7 @@
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
/**
@@ -72,7 +73,7 @@
private static final DateTimeFormatter DATE_FORMAT =
DateTimeFormatter.ofPattern("MM-dd HH:mm:ss.SSS").withZone(ZoneId.systemDefault());
- static class TimeFrame {
+ public static class TimeFrame {
public final long startMonotonicTime;
@CurrentTimeMillisLong
public final long startTime;
@@ -119,7 +120,7 @@
}
}
- static class Metadata {
+ public static class Metadata {
static final Comparator<Metadata> COMPARATOR = Comparator.comparing(Metadata::getId);
private final long mId;
@@ -262,7 +263,7 @@
public abstract static class Section {
private final String mType;
- Section(String type) {
+ protected Section(String type) {
mType = type;
}
@@ -274,7 +275,10 @@
return mType;
}
- abstract void write(TypedXmlSerializer serializer) throws IOException;
+ /**
+ * Adds the contents of this section to the XML doc.
+ */
+ public abstract void write(TypedXmlSerializer serializer) throws IOException;
/**
* Prints the section type.
@@ -290,6 +294,11 @@
*/
public interface SectionReader {
/**
+ * Returns the unique type of content handled by this reader.
+ */
+ String getType();
+
+ /**
* Reads the contents of the section using the parser. The type of the object
* read and the corresponding XML format are determined by the section type.
*/
@@ -316,12 +325,18 @@
return mMetadata.mId;
}
- void addTimeFrame(long monotonicTime, @CurrentTimeMillisLong long wallClockTime,
+ /**
+ * Adds a time frame covered by this PowerStats span
+ */
+ public void addTimeFrame(long monotonicTime, @CurrentTimeMillisLong long wallClockTime,
@DurationMillisLong long duration) {
mMetadata.mTimeFrames.add(new TimeFrame(monotonicTime, wallClockTime, duration));
}
- void addSection(Section section) {
+ /**
+ * Adds the supplied section to the span.
+ */
+ public void addSection(Section section) {
mMetadata.addSection(section.getType());
mSections.add(section);
}
@@ -354,7 +369,7 @@
@Nullable
static PowerStatsSpan read(InputStream in, TypedXmlPullParser parser,
- SectionReader sectionReader, String... sectionTypes)
+ Map<String, SectionReader> sectionReaders, String... sectionTypes)
throws IOException, XmlPullParserException {
Set<String> neededSections = Sets.newArraySet(sectionTypes);
boolean selectSections = !neededSections.isEmpty();
@@ -386,7 +401,11 @@
if (tag.equals(XML_TAG_SECTION)) {
String sectionType = parser.getAttributeValue(null, XML_ATTR_SECTION_TYPE);
if (!selectSections || neededSections.contains(sectionType)) {
- Section section = sectionReader.read(sectionType, parser);
+ Section section = null;
+ SectionReader sectionReader = sectionReaders.get(sectionType);
+ if (sectionReader != null) {
+ section = sectionReader.read(sectionType, parser);
+ }
if (section == null) {
if (selectSections) {
throw new XmlPullParserException(
@@ -396,11 +415,11 @@
@Override
public void dump(IndentingPrintWriter ipw) {
ipw.println("Unsupported PowerStatsStore section type: "
- + sectionType);
+ + sectionType);
}
@Override
- void write(TypedXmlSerializer serializer) {
+ public void write(TypedXmlSerializer serializer) {
}
};
}
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsStore.java b/services/core/java/com/android/server/power/stats/PowerStatsStore.java
index 7bcdc71..a875c30 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsStore.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsStore.java
@@ -42,6 +42,7 @@
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -66,28 +67,31 @@
private FileLock mJvmLock;
private final long mMaxStorageBytes;
private final Handler mHandler;
- private final PowerStatsSpan.SectionReader mSectionReader;
+ private final Map<String, PowerStatsSpan.SectionReader> mSectionReaders = new HashMap<>();
private volatile List<PowerStatsSpan.Metadata> mTableOfContents;
- public PowerStatsStore(@NonNull File systemDir, Handler handler,
- AggregatedPowerStatsConfig aggregatedPowerStatsConfig) {
- this(systemDir, MAX_POWER_STATS_SPAN_STORAGE_BYTES, handler,
- new DefaultSectionReader(aggregatedPowerStatsConfig));
+ public PowerStatsStore(@NonNull File systemDir, Handler handler) {
+ this(systemDir, MAX_POWER_STATS_SPAN_STORAGE_BYTES, handler);
}
@VisibleForTesting
- public PowerStatsStore(@NonNull File systemDir, long maxStorageBytes, Handler handler,
- @NonNull PowerStatsSpan.SectionReader sectionReader) {
+ public PowerStatsStore(@NonNull File systemDir, long maxStorageBytes, Handler handler) {
mSystemDir = systemDir;
mStoreDir = new File(systemDir, POWER_STATS_DIR);
mLockFile = new File(mStoreDir, DIR_LOCK_FILENAME);
mHandler = handler;
mMaxStorageBytes = maxStorageBytes;
- mSectionReader = sectionReader;
mHandler.post(this::maybeClearLegacyStore);
}
/**
+ * Registers a Reader for a section type, which is determined by `sectionReader.getType()`
+ */
+ public void addSectionReader(PowerStatsSpan.SectionReader sectionReader) {
+ mSectionReaders.put(sectionReader.getType(), sectionReader);
+ }
+
+ /**
* Returns the metadata for all {@link PowerStatsSpan}'s contained in the store.
*/
@NonNull
@@ -169,7 +173,7 @@
try {
File file = makePowerStatsSpanFilename(id);
try (InputStream inputStream = new BufferedInputStream(new FileInputStream(file))) {
- return PowerStatsSpan.read(inputStream, parser, mSectionReader, sectionTypes);
+ return PowerStatsSpan.read(inputStream, parser, mSectionReaders, sectionTypes);
} catch (IOException | XmlPullParserException e) {
Slog.wtf(TAG, "Cannot read PowerStatsSpan file: " + file, e);
}
@@ -179,41 +183,6 @@
return null;
}
- void storeAggregatedPowerStats(AggregatedPowerStats stats) {
- PowerStatsSpan span = createPowerStatsSpan(stats);
- if (span == null) {
- return;
- }
- storePowerStatsSpan(span);
- }
-
- static PowerStatsSpan createPowerStatsSpan(AggregatedPowerStats stats) {
- List<AggregatedPowerStats.ClockUpdate> clockUpdates = stats.getClockUpdates();
- if (clockUpdates.isEmpty()) {
- Slog.w(TAG, "No clock updates in aggregated power stats " + stats);
- return null;
- }
-
- long monotonicTime = clockUpdates.get(0).monotonicTime;
- long durationSum = 0;
- PowerStatsSpan span = new PowerStatsSpan(monotonicTime);
- for (int i = 0; i < clockUpdates.size(); i++) {
- AggregatedPowerStats.ClockUpdate clockUpdate = clockUpdates.get(i);
- long duration;
- if (i == clockUpdates.size() - 1) {
- duration = stats.getDuration() - durationSum;
- } else {
- duration = clockUpdate.monotonicTime - monotonicTime;
- }
- span.addTimeFrame(clockUpdate.monotonicTime, clockUpdate.currentTime, duration);
- monotonicTime = clockUpdate.monotonicTime;
- durationSum += duration;
- }
-
- span.addSection(new AggregatedPowerStatsSection(stats));
- return span;
- }
-
/**
* Stores a {@link PowerStatsSpan} containing a single section for the supplied
* battery usage stats.
@@ -344,28 +313,4 @@
}
ipw.decreaseIndent();
}
-
- private static class DefaultSectionReader implements PowerStatsSpan.SectionReader {
- private final AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
-
- DefaultSectionReader(AggregatedPowerStatsConfig aggregatedPowerStatsConfig) {
- mAggregatedPowerStatsConfig = aggregatedPowerStatsConfig;
- }
-
- @Override
- public PowerStatsSpan.Section read(String sectionType, TypedXmlPullParser parser)
- throws IOException, XmlPullParserException {
- switch (sectionType) {
- case AggregatedPowerStatsSection.TYPE:
- return new AggregatedPowerStatsSection(
- AggregatedPowerStats.createFromXml(parser,
- mAggregatedPowerStatsConfig));
- case BatteryUsageStatsSection.TYPE:
- return new BatteryUsageStatsSection(
- BatteryUsageStats.createFromXml(parser));
- default:
- return null;
- }
- }
- }
}
diff --git a/services/core/java/com/android/server/power/stats/ScreenPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/ScreenPowerStatsCollector.java
index 291f289..8371e66 100644
--- a/services/core/java/com/android/server/power/stats/ScreenPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/ScreenPowerStatsCollector.java
@@ -21,19 +21,16 @@
import android.os.BatteryStats;
import android.os.Handler;
import android.os.PersistableBundle;
-import android.util.Slog;
import android.util.SparseLongArray;
import com.android.internal.os.Clock;
import com.android.internal.os.PowerStats;
-
-import java.util.Arrays;
-import java.util.function.IntSupplier;
+import com.android.server.power.stats.format.ScreenPowerStatsLayout;
public class ScreenPowerStatsCollector extends PowerStatsCollector {
private static final String TAG = "ScreenPowerStatsCollector";
- interface ScreenUsageTimeRetriever {
+ public interface ScreenUsageTimeRetriever {
interface Callback {
void onUidTopActivityTime(int uid, long topActivityTimeMs);
}
@@ -45,30 +42,23 @@
long getScreenDozeTimeMs(int display);
}
- interface Injector {
+ public interface Injector {
Handler getHandler();
Clock getClock();
PowerStatsUidResolver getUidResolver();
long getPowerStatsCollectionThrottlePeriod(String powerComponentName);
ConsumedEnergyRetriever getConsumedEnergyRetriever();
- IntSupplier getVoltageSupplier();
ScreenUsageTimeRetriever getScreenUsageTimeRetriever();
int getDisplayCount();
}
- private static final long ENERGY_UNSPECIFIED = -1;
-
private final Injector mInjector;
private boolean mIsInitialized;
private ScreenPowerStatsLayout mLayout;
private int mDisplayCount;
private PowerStats mPowerStats;
- private ConsumedEnergyRetriever mConsumedEnergyRetriever;
- private IntSupplier mVoltageSupplier;
+ private ConsumedEnergyHelper mConsumedEnergyHelper;
private ScreenUsageTimeRetriever mScreenUsageTimeRetriever;
- private int[] mEnergyConsumerIds = new int[0];
- private long[] mLastConsumedEnergyUws;
- private int mLastVoltageMv;
private boolean mFirstSample = true;
private long[] mLastScreenOnTime;
private long[][] mLastBrightnessLevelTime;
@@ -76,7 +66,7 @@
private final SparseLongArray mLastTopActivityTime = new SparseLongArray();
private long mLastCollectionTime;
- ScreenPowerStatsCollector(Injector injector) {
+ public ScreenPowerStatsCollector(Injector injector) {
super(injector.getHandler(),
injector.getPowerStatsCollectionThrottlePeriod(
BatteryConsumer.powerComponentIdToString(
@@ -95,21 +85,12 @@
}
mDisplayCount = mInjector.getDisplayCount();
- mConsumedEnergyRetriever = mInjector.getConsumedEnergyRetriever();
- mVoltageSupplier = mInjector.getVoltageSupplier();
mScreenUsageTimeRetriever = mInjector.getScreenUsageTimeRetriever();
- mEnergyConsumerIds = mConsumedEnergyRetriever.getEnergyConsumerIds(
- EnergyConsumerType.DISPLAY);
- mLastConsumedEnergyUws = new long[mEnergyConsumerIds.length];
- Arrays.fill(mLastConsumedEnergyUws, ENERGY_UNSPECIFIED);
- mLayout = new ScreenPowerStatsLayout();
- mLayout.addDeviceScreenUsageDurationSection(mInjector.getDisplayCount());
- mLayout.addDeviceSectionEnergyConsumers(mEnergyConsumerIds.length);
- mLayout.addDeviceSectionUsageDuration();
- mLayout.addDeviceSectionPowerEstimate();
- mLayout.addUidTopActivitiyDuration();
- mLayout.addUidSectionPowerEstimate();
+ mConsumedEnergyHelper = new ConsumedEnergyHelper(mInjector.getConsumedEnergyRetriever(),
+ EnergyConsumerType.DISPLAY);
+ mLayout = new ScreenPowerStatsLayout(mConsumedEnergyHelper.getEnergyConsumerCount(),
+ mInjector.getDisplayCount());
PersistableBundle extras = new PersistableBundle();
mLayout.toExtras(extras);
@@ -129,14 +110,12 @@
}
@Override
- protected PowerStats collectStats() {
+ public PowerStats collectStats() {
if (!ensureInitialized()) {
return null;
}
- if (mEnergyConsumerIds.length != 0) {
- collectEnergyConsumers();
- }
+ mConsumedEnergyHelper.collectConsumedEnergy(mPowerStats, mLayout);
for (int display = 0; display < mDisplayCount; display++) {
long screenOnTimeMs = mScreenUsageTimeRetriever.getScreenOnTimeMs(display);
@@ -192,34 +171,6 @@
return mPowerStats;
}
- 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) {
mLastTopActivityTime.delete(uid);
diff --git a/services/core/java/com/android/server/power/stats/WifiPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/WifiPowerStatsCollector.java
index 90981ada..7a84b05 100644
--- a/services/core/java/com/android/server/power/stats/WifiPowerStatsCollector.java
+++ b/services/core/java/com/android/server/power/stats/WifiPowerStatsCollector.java
@@ -28,12 +28,11 @@
import com.android.internal.os.Clock;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.WifiPowerStatsLayout;
-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 {
@@ -41,15 +40,13 @@
private static final long WIFI_ACTIVITY_REQUEST_TIMEOUT = 20000;
- private static final long ENERGY_UNSPECIFIED = -1;
-
interface Observer {
void onWifiPowerStatsRetrieved(WifiActivityEnergyInfo info,
List<BatteryStatsImpl.NetworkStatsDelta> delta, long elapsedRealtimeMs,
long uptimeMs);
}
- interface WifiStatsRetriever {
+ public interface WifiStatsRetriever {
interface Callback {
void onWifiScanTime(int uid, long scanTimeMs, long batchScanTimeMs);
}
@@ -58,14 +55,13 @@
long getWifiActiveDuration();
}
- interface Injector {
+ public interface Injector {
Handler getHandler();
Clock getClock();
PowerStatsUidResolver getUidResolver();
long getPowerStatsCollectionThrottlePeriod(String powerComponentName);
PackageManager getPackageManager();
ConsumedEnergyRetriever getConsumedEnergyRetriever();
- IntSupplier getVoltageSupplier();
Supplier<NetworkStats> getWifiNetworkStatsSupplier();
WifiManager getWifiManager();
WifiStatsRetriever getWifiStatsRetriever();
@@ -83,13 +79,9 @@
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 ConsumedEnergyHelper mConsumedEnergyHelper;
private WifiActivityEnergyInfo mLastWifiActivityInfo;
private NetworkStats mLastNetworkStats;
- private long[] mLastConsumedEnergyUws;
- private int mLastVoltageMv;
private static class WifiScanTimes {
public long basicScanTimeMs;
@@ -99,7 +91,7 @@
private final SparseArray<WifiScanTimes> mLastScanTimes = new SparseArray<>();
private long mLastWifiActiveDuration;
- WifiPowerStatsCollector(Injector injector, Observer observer) {
+ public WifiPowerStatsCollector(Injector injector, Observer observer) {
super(injector.getHandler(), injector.getPowerStatsCollectionThrottlePeriod(
BatteryConsumer.powerComponentIdToString(
BatteryConsumer.POWER_COMPONENT_WIFI)),
@@ -128,25 +120,17 @@
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);
+ mConsumedEnergyHelper = new ConsumedEnergyHelper(mInjector.getConsumedEnergyRetriever(),
+ EnergyConsumerType.WIFI);
- mLayout = new WifiPowerStatsLayout();
- mLayout.addDeviceWifiActivity(mPowerReportingSupported);
- mLayout.addDeviceSectionEnergyConsumers(mEnergyConsumerIds.length);
- mLayout.addUidNetworkStats();
- mLayout.addDeviceSectionUsageDuration();
- mLayout.addDeviceSectionPowerEstimate();
- mLayout.addUidSectionPowerEstimate();
+ mLayout = new WifiPowerStatsLayout(mConsumedEnergyHelper.getEnergyConsumerCount(),
+ mPowerReportingSupported);
PersistableBundle extras = new PersistableBundle();
mLayout.toExtras(extras);
@@ -162,7 +146,7 @@
}
@Override
- protected PowerStats collectStats() {
+ public PowerStats collectStats() {
if (!ensureInitialized()) {
return null;
}
@@ -176,9 +160,7 @@
List<BatteryStatsImpl.NetworkStatsDelta> networkStatsDeltas = collectNetworkStats();
collectWifiScanTime();
- if (mEnergyConsumerIds.length != 0) {
- collectEnergyConsumers();
- }
+ mConsumedEnergyHelper.collectConsumedEnergy(mPowerStats, mLayout);
if (mObserver != null) {
mObserver.onWifiPowerStatsRetrieved(activityInfo, networkStatsDeltas,
@@ -318,34 +300,6 @@
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);
diff --git a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/AmbientDisplayPowerStatsLayout.java
similarity index 72%
copy from services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
copy to services/core/java/com/android/server/power/stats/format/AmbientDisplayPowerStatsLayout.java
index 502337c..1b99b0d 100644
--- a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/AmbientDisplayPowerStatsLayout.java
@@ -13,12 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.server.power.stats.format;
-package com.android.server.power.stats;
-
-class BinaryStatePowerStatsLayout extends EnergyConsumerPowerStatsLayout {
- BinaryStatePowerStatsLayout() {
- addDeviceSectionUsageDuration();
- addUidSectionUsageDuration();
+public class AmbientDisplayPowerStatsLayout extends PowerStatsLayout {
+ public AmbientDisplayPowerStatsLayout() {
+ addDeviceSectionPowerEstimate();
}
}
diff --git a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/BinaryStatePowerStatsLayout.java
similarity index 68%
copy from services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
copy to services/core/java/com/android/server/power/stats/format/BinaryStatePowerStatsLayout.java
index 502337c..4a26d83 100644
--- a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/BinaryStatePowerStatsLayout.java
@@ -14,11 +14,17 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
-class BinaryStatePowerStatsLayout extends EnergyConsumerPowerStatsLayout {
- BinaryStatePowerStatsLayout() {
+import com.android.internal.os.PowerStats;
+
+public class BinaryStatePowerStatsLayout extends EnergyConsumerPowerStatsLayout {
+ public BinaryStatePowerStatsLayout() {
addDeviceSectionUsageDuration();
addUidSectionUsageDuration();
}
+
+ public BinaryStatePowerStatsLayout(PowerStats.Descriptor descriptor) {
+ super(descriptor);
+ }
}
diff --git a/services/core/java/com/android/server/power/stats/BluetoothPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/BluetoothPowerStatsLayout.java
similarity index 88%
rename from services/core/java/com/android/server/power/stats/BluetoothPowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/BluetoothPowerStatsLayout.java
index 9358b5e..534a9f7 100644
--- a/services/core/java/com/android/server/power/stats/BluetoothPowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/BluetoothPowerStatsLayout.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
import android.annotation.NonNull;
import android.os.PersistableBundle;
@@ -37,21 +37,49 @@
private int mUidTxBytesPosition;
private int mUidScanTimePosition;
- BluetoothPowerStatsLayout() {
+ public BluetoothPowerStatsLayout(int energyConsumerCount) {
+ addDeviceBluetoothControllerActivity();
+ addDeviceSectionEnergyConsumers(energyConsumerCount);
+ addDeviceSectionUsageDuration();
+ addDeviceSectionPowerEstimate();
+ addUidTrafficStats();
+ addUidSectionPowerEstimate();
}
- BluetoothPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
+ public BluetoothPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
super(descriptor);
+ PersistableBundle extras = descriptor.extras;
+ mDeviceRxTimePosition = extras.getInt(EXTRA_DEVICE_RX_TIME_POSITION);
+ mDeviceTxTimePosition = extras.getInt(EXTRA_DEVICE_TX_TIME_POSITION);
+ mDeviceIdleTimePosition = extras.getInt(EXTRA_DEVICE_IDLE_TIME_POSITION);
+ mDeviceScanTimePosition = extras.getInt(EXTRA_DEVICE_SCAN_TIME_POSITION);
+ mUidRxBytesPosition = extras.getInt(EXTRA_UID_RX_BYTES_POSITION);
+ mUidTxBytesPosition = extras.getInt(EXTRA_UID_TX_BYTES_POSITION);
+ mUidScanTimePosition = extras.getInt(EXTRA_UID_SCAN_TIME_POSITION);
}
- void addDeviceBluetoothControllerActivity() {
+ /**
+ * Copies the elements of the stats array layout into <code>extras</code>
+ */
+ public void toExtras(PersistableBundle extras) {
+ super.toExtras(extras);
+ extras.putInt(EXTRA_DEVICE_RX_TIME_POSITION, mDeviceRxTimePosition);
+ extras.putInt(EXTRA_DEVICE_TX_TIME_POSITION, mDeviceTxTimePosition);
+ extras.putInt(EXTRA_DEVICE_IDLE_TIME_POSITION, mDeviceIdleTimePosition);
+ extras.putInt(EXTRA_DEVICE_SCAN_TIME_POSITION, mDeviceScanTimePosition);
+ extras.putInt(EXTRA_UID_RX_BYTES_POSITION, mUidRxBytesPosition);
+ extras.putInt(EXTRA_UID_TX_BYTES_POSITION, mUidTxBytesPosition);
+ extras.putInt(EXTRA_UID_SCAN_TIME_POSITION, mUidScanTimePosition);
+ }
+
+ private void addDeviceBluetoothControllerActivity() {
mDeviceRxTimePosition = addDeviceSection(1, "rx");
mDeviceTxTimePosition = addDeviceSection(1, "tx");
mDeviceIdleTimePosition = addDeviceSection(1, "idle");
mDeviceScanTimePosition = addDeviceSection(1, "scan", FLAG_OPTIONAL);
}
- void addUidTrafficStats() {
+ private void addUidTrafficStats() {
mUidRxBytesPosition = addUidSection(1, "rx-B");
mUidTxBytesPosition = addUidSection(1, "tx-B");
mUidScanTimePosition = addUidSection(1, "scan", FLAG_OPTIONAL);
@@ -112,32 +140,4 @@
public long getUidScanTime(long[] stats) {
return stats[mUidScanTimePosition];
}
-
- /**
- * Copies the elements of the stats array layout into <code>extras</code>
- */
- public void toExtras(PersistableBundle extras) {
- super.toExtras(extras);
- extras.putInt(EXTRA_DEVICE_RX_TIME_POSITION, mDeviceRxTimePosition);
- extras.putInt(EXTRA_DEVICE_TX_TIME_POSITION, mDeviceTxTimePosition);
- extras.putInt(EXTRA_DEVICE_IDLE_TIME_POSITION, mDeviceIdleTimePosition);
- extras.putInt(EXTRA_DEVICE_SCAN_TIME_POSITION, mDeviceScanTimePosition);
- extras.putInt(EXTRA_UID_RX_BYTES_POSITION, mUidRxBytesPosition);
- extras.putInt(EXTRA_UID_TX_BYTES_POSITION, mUidTxBytesPosition);
- extras.putInt(EXTRA_UID_SCAN_TIME_POSITION, mUidScanTimePosition);
- }
-
- /**
- * Retrieves elements of the stats array layout from <code>extras</code>
- */
- public void fromExtras(PersistableBundle extras) {
- super.fromExtras(extras);
- mDeviceRxTimePosition = extras.getInt(EXTRA_DEVICE_RX_TIME_POSITION);
- mDeviceTxTimePosition = extras.getInt(EXTRA_DEVICE_TX_TIME_POSITION);
- mDeviceIdleTimePosition = extras.getInt(EXTRA_DEVICE_IDLE_TIME_POSITION);
- mDeviceScanTimePosition = extras.getInt(EXTRA_DEVICE_SCAN_TIME_POSITION);
- mUidRxBytesPosition = extras.getInt(EXTRA_UID_RX_BYTES_POSITION);
- mUidTxBytesPosition = extras.getInt(EXTRA_UID_TX_BYTES_POSITION);
- mUidScanTimePosition = extras.getInt(EXTRA_UID_SCAN_TIME_POSITION);
- }
}
diff --git a/services/core/java/com/android/server/power/stats/CpuPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/CpuPowerStatsLayout.java
similarity index 85%
rename from services/core/java/com/android/server/power/stats/CpuPowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/CpuPowerStatsLayout.java
index 2a02bd0..3186d7d 100644
--- a/services/core/java/com/android/server/power/stats/CpuPowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/CpuPowerStatsLayout.java
@@ -14,10 +14,13 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
+import android.annotation.NonNull;
import android.os.PersistableBundle;
+import com.android.internal.os.PowerStats;
+
/**
* Captures the positions and lengths of sections of the stats array, such as time-in-state,
* power usage estimates etc.
@@ -40,10 +43,59 @@
private int[] mScalingStepToPowerBracketMap;
+ public CpuPowerStatsLayout(int energyConsumerCount, int cpuScalingPolicyCount,
+ int[] scalingStepToPowerBracketMap) {
+ addDeviceSectionCpuTimeByScalingStep(scalingStepToPowerBracketMap.length);
+ addDeviceSectionCpuTimeByCluster(cpuScalingPolicyCount);
+ addDeviceSectionUsageDuration();
+ addDeviceSectionEnergyConsumers(energyConsumerCount);
+ addDeviceSectionPowerEstimate();
+ addUidSectionCpuTimeByPowerBracket(scalingStepToPowerBracketMap);
+ addUidSectionPowerEstimate();
+ }
+
+ public CpuPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
+ super(descriptor);
+ PersistableBundle extras = descriptor.extras;
+ mDeviceCpuTimeByScalingStepPosition =
+ extras.getInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_POSITION);
+ mDeviceCpuTimeByScalingStepCount =
+ extras.getInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_COUNT);
+ mDeviceCpuTimeByClusterPosition =
+ extras.getInt(EXTRA_DEVICE_TIME_BY_CLUSTER_POSITION);
+ mDeviceCpuTimeByClusterCount =
+ extras.getInt(EXTRA_DEVICE_TIME_BY_CLUSTER_COUNT);
+ mUidPowerBracketsPosition = extras.getInt(EXTRA_UID_BRACKETS_POSITION);
+ mScalingStepToPowerBracketMap =
+ getIntArray(extras, EXTRA_UID_STATS_SCALING_STEP_TO_POWER_BRACKET);
+ if (mScalingStepToPowerBracketMap == null) {
+ mScalingStepToPowerBracketMap = new int[mDeviceCpuTimeByScalingStepCount];
+ }
+ updatePowerBracketCount();
+ }
+
+ /**
+ * Copies the elements of the stats array layout into <code>extras</code>
+ */
+ public void toExtras(PersistableBundle extras) {
+ super.toExtras(extras);
+ extras.putInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_POSITION,
+ mDeviceCpuTimeByScalingStepPosition);
+ extras.putInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_COUNT,
+ mDeviceCpuTimeByScalingStepCount);
+ extras.putInt(EXTRA_DEVICE_TIME_BY_CLUSTER_POSITION,
+ mDeviceCpuTimeByClusterPosition);
+ extras.putInt(EXTRA_DEVICE_TIME_BY_CLUSTER_COUNT,
+ mDeviceCpuTimeByClusterCount);
+ extras.putInt(EXTRA_UID_BRACKETS_POSITION, mUidPowerBracketsPosition);
+ putIntArray(extras, EXTRA_UID_STATS_SCALING_STEP_TO_POWER_BRACKET,
+ mScalingStepToPowerBracketMap);
+ }
+
/**
* Declare that the stats array has a section capturing CPU time per scaling step
*/
- public void addDeviceSectionCpuTimeByScalingStep(int scalingStepCount) {
+ private void addDeviceSectionCpuTimeByScalingStep(int scalingStepCount) {
mDeviceCpuTimeByScalingStepPosition = addDeviceSection(scalingStepCount, "steps");
mDeviceCpuTimeByScalingStepCount = scalingStepCount;
}
@@ -71,7 +123,7 @@
/**
* Declare that the stats array has a section capturing CPU time in each cluster
*/
- public void addDeviceSectionCpuTimeByCluster(int clusterCount) {
+ private void addDeviceSectionCpuTimeByCluster(int clusterCount) {
mDeviceCpuTimeByClusterPosition = addDeviceSection(clusterCount, "clusters");
mDeviceCpuTimeByClusterCount = clusterCount;
}
@@ -99,7 +151,7 @@
/**
* Declare that the UID stats array has a section capturing CPU time per power bracket.
*/
- public void addUidSectionCpuTimeByPowerBracket(int[] scalingStepToPowerBracketMap) {
+ private void addUidSectionCpuTimeByPowerBracket(int[] scalingStepToPowerBracketMap) {
mScalingStepToPowerBracketMap = scalingStepToPowerBracketMap;
updatePowerBracketCount();
mUidPowerBracketsPosition = addUidSection(mUidPowerBracketCount, "time");
@@ -135,44 +187,4 @@
public long getUidTimeByPowerBracket(long[] stats, int bracket) {
return stats[mUidPowerBracketsPosition + bracket];
}
-
- /**
- * Copies the elements of the stats array layout into <code>extras</code>
- */
- public void toExtras(PersistableBundle extras) {
- super.toExtras(extras);
- extras.putInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_POSITION,
- mDeviceCpuTimeByScalingStepPosition);
- extras.putInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_COUNT,
- mDeviceCpuTimeByScalingStepCount);
- extras.putInt(EXTRA_DEVICE_TIME_BY_CLUSTER_POSITION,
- mDeviceCpuTimeByClusterPosition);
- extras.putInt(EXTRA_DEVICE_TIME_BY_CLUSTER_COUNT,
- mDeviceCpuTimeByClusterCount);
- extras.putInt(EXTRA_UID_BRACKETS_POSITION, mUidPowerBracketsPosition);
- putIntArray(extras, EXTRA_UID_STATS_SCALING_STEP_TO_POWER_BRACKET,
- mScalingStepToPowerBracketMap);
- }
-
- /**
- * Retrieves elements of the stats array layout from <code>extras</code>
- */
- public void fromExtras(PersistableBundle extras) {
- super.fromExtras(extras);
- mDeviceCpuTimeByScalingStepPosition =
- extras.getInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_POSITION);
- mDeviceCpuTimeByScalingStepCount =
- extras.getInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_COUNT);
- mDeviceCpuTimeByClusterPosition =
- extras.getInt(EXTRA_DEVICE_TIME_BY_CLUSTER_POSITION);
- mDeviceCpuTimeByClusterCount =
- extras.getInt(EXTRA_DEVICE_TIME_BY_CLUSTER_COUNT);
- mUidPowerBracketsPosition = extras.getInt(EXTRA_UID_BRACKETS_POSITION);
- mScalingStepToPowerBracketMap =
- getIntArray(extras, EXTRA_UID_STATS_SCALING_STEP_TO_POWER_BRACKET);
- if (mScalingStepToPowerBracketMap == null) {
- mScalingStepToPowerBracketMap = new int[mDeviceCpuTimeByScalingStepCount];
- }
- updatePowerBracketCount();
- }
}
diff --git a/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/EnergyConsumerPowerStatsLayout.java
similarity index 80%
rename from services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/EnergyConsumerPowerStatsLayout.java
index 8430f56..e7a4822 100644
--- a/services/core/java/com/android/server/power/stats/EnergyConsumerPowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/EnergyConsumerPowerStatsLayout.java
@@ -14,10 +14,12 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
-class EnergyConsumerPowerStatsLayout extends PowerStatsLayout {
- EnergyConsumerPowerStatsLayout() {
+import com.android.internal.os.PowerStats;
+
+public class EnergyConsumerPowerStatsLayout extends PowerStatsLayout {
+ public EnergyConsumerPowerStatsLayout() {
// Add a section for consumed energy, even if the specific device does not
// have support EnergyConsumers. This is done to guarantee format compatibility between
// PowerStats created by a PowerStatsCollector and those produced by a PowerStatsProcessor.
@@ -30,4 +32,8 @@
addUidSectionEnergyConsumers(1);
addUidSectionPowerEstimate();
}
+
+ public EnergyConsumerPowerStatsLayout(PowerStats.Descriptor descriptor) {
+ super(descriptor);
+ }
}
diff --git a/services/core/java/com/android/server/power/stats/GnssPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/GnssPowerStatsLayout.java
similarity index 81%
rename from services/core/java/com/android/server/power/stats/GnssPowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/GnssPowerStatsLayout.java
index 9a1317d..b70b173 100644
--- a/services/core/java/com/android/server/power/stats/GnssPowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/GnssPowerStatsLayout.java
@@ -14,28 +14,31 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
+import android.annotation.NonNull;
import android.location.GnssSignalQuality;
import android.os.PersistableBundle;
-class GnssPowerStatsLayout extends BinaryStatePowerStatsLayout {
+import com.android.internal.os.PowerStats;
+
+public class GnssPowerStatsLayout extends BinaryStatePowerStatsLayout {
private static final String EXTRA_DEVICE_TIME_SIGNAL_LEVEL_POSITION = "dt-sig";
private static final String EXTRA_UID_TIME_SIGNAL_LEVEL_POSITION = "ut-sig";
- private int mDeviceSignalLevelTimePosition;
- private int mUidSignalLevelTimePosition;
+ private final int mDeviceSignalLevelTimePosition;
+ private final int mUidSignalLevelTimePosition;
- GnssPowerStatsLayout() {
+ public GnssPowerStatsLayout() {
mDeviceSignalLevelTimePosition = addDeviceSection(
GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS, "level");
mUidSignalLevelTimePosition = addUidSection(
GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS, "level");
}
- @Override
- public void fromExtras(PersistableBundle extras) {
- super.fromExtras(extras);
+ public GnssPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
+ super(descriptor);
+ PersistableBundle extras = descriptor.extras;
mDeviceSignalLevelTimePosition = extras.getInt(EXTRA_DEVICE_TIME_SIGNAL_LEVEL_POSITION);
mUidSignalLevelTimePosition = extras.getInt(EXTRA_UID_TIME_SIGNAL_LEVEL_POSITION);
}
diff --git a/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/MobileRadioPowerStatsLayout.java
similarity index 79%
rename from services/core/java/com/android/server/power/stats/MobileRadioPowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/MobileRadioPowerStatsLayout.java
index 07d78f8..da6fc41 100644
--- a/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/MobileRadioPowerStatsLayout.java
@@ -14,10 +14,12 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
import android.annotation.NonNull;
+import android.os.BatteryStats;
import android.os.PersistableBundle;
+import android.telephony.AccessNetworkConstants;
import android.telephony.ModemActivityInfo;
import android.util.Slog;
import android.util.SparseArray;
@@ -28,7 +30,7 @@
* Captures the positions and lengths of sections of the stats array, such as time-in-state,
* power usage estimates etc.
*/
-class MobileRadioPowerStatsLayout extends PowerStatsLayout {
+public class MobileRadioPowerStatsLayout extends PowerStatsLayout {
private static final String TAG = "MobileRadioPowerStatsLayout";
private static final String EXTRA_DEVICE_SLEEP_TIME_POSITION = "dt-sleep";
private static final String EXTRA_DEVICE_IDLE_TIME_POSITION = "dt-idle";
@@ -56,27 +58,95 @@
private int mUidRxPacketsPosition;
private int mUidTxPacketsPosition;
- MobileRadioPowerStatsLayout() {
+ public MobileRadioPowerStatsLayout(int energyConsumerCount) {
+ addDeviceMobileActivity();
+ addDeviceSectionEnergyConsumers(energyConsumerCount);
+ addStateStats();
+ addUidNetworkStats();
+ addDeviceSectionUsageDuration();
+ addDeviceSectionPowerEstimate();
+ addUidSectionPowerEstimate();
}
- MobileRadioPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
+ public MobileRadioPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
super(descriptor);
+ PersistableBundle extras = descriptor.extras;
+ mDeviceSleepTimePosition = extras.getInt(EXTRA_DEVICE_SLEEP_TIME_POSITION);
+ mDeviceIdleTimePosition = extras.getInt(EXTRA_DEVICE_IDLE_TIME_POSITION);
+ mDeviceScanTimePosition = extras.getInt(EXTRA_DEVICE_SCAN_TIME_POSITION);
+ mDeviceCallTimePosition = extras.getInt(EXTRA_DEVICE_CALL_TIME_POSITION);
+ mDeviceCallPowerPosition = extras.getInt(EXTRA_DEVICE_CALL_POWER_POSITION);
+ mStateRxTimePosition = extras.getInt(EXTRA_STATE_RX_TIME_POSITION);
+ mStateTxTimesPosition = extras.getInt(EXTRA_STATE_TX_TIMES_POSITION);
+ mStateTxTimesCount = extras.getInt(EXTRA_STATE_TX_TIMES_COUNT);
+ 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);
}
- void addDeviceMobileActivity() {
+ /**
+ * Copies the elements of the stats array layout into <code>extras</code>
+ */
+ public void toExtras(PersistableBundle extras) {
+ super.toExtras(extras);
+ extras.putInt(EXTRA_DEVICE_SLEEP_TIME_POSITION, mDeviceSleepTimePosition);
+ extras.putInt(EXTRA_DEVICE_IDLE_TIME_POSITION, mDeviceIdleTimePosition);
+ extras.putInt(EXTRA_DEVICE_SCAN_TIME_POSITION, mDeviceScanTimePosition);
+ extras.putInt(EXTRA_DEVICE_CALL_TIME_POSITION, mDeviceCallTimePosition);
+ extras.putInt(EXTRA_DEVICE_CALL_POWER_POSITION, mDeviceCallPowerPosition);
+ extras.putInt(EXTRA_STATE_RX_TIME_POSITION, mStateRxTimePosition);
+ extras.putInt(EXTRA_STATE_TX_TIMES_POSITION, mStateTxTimesPosition);
+ extras.putInt(EXTRA_STATE_TX_TIMES_COUNT, mStateTxTimesCount);
+ 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);
+ }
+
+ public static int makeStateKey(int rat, int freqRange) {
+ if (rat == BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR) {
+ return rat | (freqRange << 8);
+ } else {
+ return rat;
+ }
+ }
+
+ @BatteryStats.RadioAccessTechnology
+ public static int mapRadioAccessNetworkTypeToRadioAccessTechnology(
+ @AccessNetworkConstants.RadioAccessNetworkType int networkType) {
+ switch (networkType) {
+ case AccessNetworkConstants.AccessNetworkType.NGRAN:
+ return BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR;
+ case AccessNetworkConstants.AccessNetworkType.EUTRAN:
+ return BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE;
+ case AccessNetworkConstants.AccessNetworkType.UNKNOWN: //fallthrough
+ case AccessNetworkConstants.AccessNetworkType.GERAN: //fallthrough
+ case AccessNetworkConstants.AccessNetworkType.UTRAN: //fallthrough
+ case AccessNetworkConstants.AccessNetworkType.CDMA2000: //fallthrough
+ case AccessNetworkConstants.AccessNetworkType.IWLAN:
+ return BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
+ default:
+ Slog.w(TAG,
+ "Unhandled RadioAccessNetworkType (" + networkType + "), mapping to OTHER");
+ return BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
+ }
+ }
+
+ private void addDeviceMobileActivity() {
mDeviceSleepTimePosition = addDeviceSection(1, "sleep");
mDeviceIdleTimePosition = addDeviceSection(1, "idle");
mDeviceScanTimePosition = addDeviceSection(1, "scan");
mDeviceCallTimePosition = addDeviceSection(1, "call", FLAG_OPTIONAL);
}
- void addStateStats() {
+ private void addStateStats() {
mStateRxTimePosition = addStateSection(1, "rx");
mStateTxTimesCount = ModemActivityInfo.getNumTxPowerLevels();
mStateTxTimesPosition = addStateSection(mStateTxTimesCount, "tx");
}
- void addUidNetworkStats() {
+ private void addUidNetworkStats() {
mUidRxPacketsPosition = addUidSection(1, "rx-pkts");
mUidRxBytesPosition = addUidSection(1, "rx-B");
mUidTxPacketsPosition = addUidSection(1, "tx-pkts");
@@ -84,7 +154,7 @@
}
@Override
- public void addDeviceSectionPowerEstimate() {
+ protected void addDeviceSectionPowerEstimate() {
super.addDeviceSectionPowerEstimate();
// Printed as part of the PhoneCallPowerStatsProcessor
mDeviceCallPowerPosition = addDeviceSection(1, "call-power", FLAG_HIDDEN);
@@ -178,44 +248,6 @@
return stats[mUidTxPacketsPosition];
}
- /**
- * Copies the elements of the stats array layout into <code>extras</code>
- */
- public void toExtras(PersistableBundle extras) {
- super.toExtras(extras);
- extras.putInt(EXTRA_DEVICE_SLEEP_TIME_POSITION, mDeviceSleepTimePosition);
- extras.putInt(EXTRA_DEVICE_IDLE_TIME_POSITION, mDeviceIdleTimePosition);
- extras.putInt(EXTRA_DEVICE_SCAN_TIME_POSITION, mDeviceScanTimePosition);
- extras.putInt(EXTRA_DEVICE_CALL_TIME_POSITION, mDeviceCallTimePosition);
- extras.putInt(EXTRA_DEVICE_CALL_POWER_POSITION, mDeviceCallPowerPosition);
- extras.putInt(EXTRA_STATE_RX_TIME_POSITION, mStateRxTimePosition);
- extras.putInt(EXTRA_STATE_TX_TIMES_POSITION, mStateTxTimesPosition);
- extras.putInt(EXTRA_STATE_TX_TIMES_COUNT, mStateTxTimesCount);
- 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);
- }
-
- /**
- * Retrieves elements of the stats array layout from <code>extras</code>
- */
- public void fromExtras(PersistableBundle extras) {
- super.fromExtras(extras);
- mDeviceSleepTimePosition = extras.getInt(EXTRA_DEVICE_SLEEP_TIME_POSITION);
- mDeviceIdleTimePosition = extras.getInt(EXTRA_DEVICE_IDLE_TIME_POSITION);
- mDeviceScanTimePosition = extras.getInt(EXTRA_DEVICE_SCAN_TIME_POSITION);
- mDeviceCallTimePosition = extras.getInt(EXTRA_DEVICE_CALL_TIME_POSITION);
- mDeviceCallPowerPosition = extras.getInt(EXTRA_DEVICE_CALL_POWER_POSITION);
- mStateRxTimePosition = extras.getInt(EXTRA_STATE_RX_TIME_POSITION);
- mStateTxTimesPosition = extras.getInt(EXTRA_STATE_TX_TIMES_POSITION);
- mStateTxTimesCount = extras.getInt(EXTRA_STATE_TX_TIMES_COUNT);
- 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);
- }
-
public void addRxTxTimesForRat(SparseArray<long[]> stateStats, int networkType, int freqRange,
long rxTime, int[] txTime) {
if (txTime.length != mStateTxTimesCount) {
@@ -239,9 +271,8 @@
return;
}
- int rat = MobileRadioPowerStatsCollector.mapRadioAccessNetworkTypeToRadioAccessTechnology(
- networkType);
- int stateKey = MobileRadioPowerStatsCollector.makeStateKey(rat, freqRange);
+ int rat = mapRadioAccessNetworkTypeToRadioAccessTechnology(networkType);
+ int stateKey = makeStateKey(rat, freqRange);
long[] stats = stateStats.get(stateKey);
if (stats == null) {
stats = new long[getStateStatsArrayLength()];
diff --git a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/PhoneCallPowerStatsLayout.java
similarity index 72%
rename from services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/PhoneCallPowerStatsLayout.java
index 502337c..5a34148 100644
--- a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/PhoneCallPowerStatsLayout.java
@@ -13,12 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.server.power.stats.format;
-package com.android.server.power.stats;
-
-class BinaryStatePowerStatsLayout extends EnergyConsumerPowerStatsLayout {
- BinaryStatePowerStatsLayout() {
- addDeviceSectionUsageDuration();
- addUidSectionUsageDuration();
+public class PhoneCallPowerStatsLayout extends PowerStatsLayout {
+ public PhoneCallPowerStatsLayout() {
+ addDeviceSectionPowerEstimate();
}
}
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/PowerStatsLayout.java
similarity index 91%
rename from services/core/java/com/android/server/power/stats/PowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/PowerStatsLayout.java
index 62abfc6..d070919 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/PowerStatsLayout.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
import android.os.PersistableBundle;
import android.util.Slog;
@@ -36,7 +36,7 @@
private static final String EXTRA_UID_ENERGY_CONSUMERS_COUNT = "uec";
private static final String EXTRA_UID_POWER_POSITION = "up";
- protected static final int UNSUPPORTED = -1;
+ public static final int UNSUPPORTED = -1;
protected static final double MILLI_TO_NANO_MULTIPLIER = 1000000.0;
protected static final int FLAG_OPTIONAL = 1;
protected static final int FLAG_HIDDEN = 2;
@@ -46,9 +46,9 @@
private int mStateStatsArrayLength;
private int mUidStatsArrayLength;
- private StringBuilder mDeviceFormat = new StringBuilder();
- private StringBuilder mStateFormat = new StringBuilder();
- private StringBuilder mUidFormat = new StringBuilder();
+ private final StringBuilder mDeviceFormat = new StringBuilder();
+ private final StringBuilder mStateFormat = new StringBuilder();
+ private final StringBuilder mUidFormat = new StringBuilder();
protected int mDeviceDurationPosition = UNSUPPORTED;
private int mDeviceEnergyConsumerPosition;
@@ -63,7 +63,32 @@
}
public PowerStatsLayout(PowerStats.Descriptor descriptor) {
- fromExtras(descriptor.extras);
+ PersistableBundle extras = descriptor.extras;
+ mDeviceDurationPosition = extras.getInt(EXTRA_DEVICE_DURATION_POSITION);
+ mDeviceEnergyConsumerPosition = extras.getInt(EXTRA_DEVICE_ENERGY_CONSUMERS_POSITION);
+ mDeviceEnergyConsumerCount = extras.getInt(EXTRA_DEVICE_ENERGY_CONSUMERS_COUNT);
+ mDevicePowerEstimatePosition = extras.getInt(EXTRA_DEVICE_POWER_POSITION);
+ mUidDurationPosition = extras.getInt(EXTRA_UID_DURATION_POSITION);
+ mUidEnergyConsumerPosition = extras.getInt(EXTRA_UID_ENERGY_CONSUMERS_POSITION);
+ mUidEnergyConsumerCount = extras.getInt(EXTRA_UID_ENERGY_CONSUMERS_COUNT);
+ mUidPowerEstimatePosition = extras.getInt(EXTRA_UID_POWER_POSITION);
+ }
+
+ /**
+ * Copies the elements of the stats array layout into <code>extras</code>
+ */
+ public void toExtras(PersistableBundle extras) {
+ extras.putInt(EXTRA_DEVICE_DURATION_POSITION, mDeviceDurationPosition);
+ extras.putInt(EXTRA_DEVICE_ENERGY_CONSUMERS_POSITION, mDeviceEnergyConsumerPosition);
+ extras.putInt(EXTRA_DEVICE_ENERGY_CONSUMERS_COUNT, mDeviceEnergyConsumerCount);
+ extras.putInt(EXTRA_DEVICE_POWER_POSITION, mDevicePowerEstimatePosition);
+ extras.putInt(EXTRA_UID_DURATION_POSITION, mUidDurationPosition);
+ extras.putInt(EXTRA_UID_ENERGY_CONSUMERS_POSITION, mUidEnergyConsumerPosition);
+ extras.putInt(EXTRA_UID_ENERGY_CONSUMERS_COUNT, mUidEnergyConsumerCount);
+ extras.putInt(EXTRA_UID_POWER_POSITION, mUidPowerEstimatePosition);
+ extras.putString(PowerStats.Descriptor.EXTRA_DEVICE_STATS_FORMAT, mDeviceFormat.toString());
+ extras.putString(PowerStats.Descriptor.EXTRA_STATE_STATS_FORMAT, mStateFormat.toString());
+ extras.putString(PowerStats.Descriptor.EXTRA_UID_STATS_FORMAT, mUidFormat.toString());
}
public int getDeviceStatsArrayLength() {
@@ -141,7 +166,7 @@
/**
* Declare that the stats array has a section capturing usage duration
*/
- public void addDeviceSectionUsageDuration() {
+ protected void addDeviceSectionUsageDuration() {
mDeviceDurationPosition = addDeviceSection(1, "usage", FLAG_OPTIONAL);
}
@@ -163,7 +188,7 @@
* Declares that the stats array has a section capturing EnergyConsumer data from
* PowerStatsService.
*/
- public void addDeviceSectionEnergyConsumers(int energyConsumerCount) {
+ protected void addDeviceSectionEnergyConsumers(int energyConsumerCount) {
mDeviceEnergyConsumerPosition = addDeviceSection(energyConsumerCount, "energy",
FLAG_OPTIONAL);
mDeviceEnergyConsumerCount = energyConsumerCount;
@@ -192,7 +217,7 @@
/**
* Declare that the stats array has a section capturing a power estimate
*/
- public void addDeviceSectionPowerEstimate() {
+ protected void addDeviceSectionPowerEstimate() {
mDevicePowerEstimatePosition = addDeviceSection(1, "power",
FLAG_FORMAT_AS_POWER | FLAG_OPTIONAL);
}
@@ -215,14 +240,14 @@
/**
* Declare that the UID stats array has a section capturing usage duration
*/
- public void addUidSectionUsageDuration() {
+ protected void addUidSectionUsageDuration() {
mUidDurationPosition = addUidSection(1, "time");
}
/**
* Declare that the UID stats array has a section capturing a power estimate
*/
- public void addUidSectionPowerEstimate() {
+ protected void addUidSectionPowerEstimate() {
mUidPowerEstimatePosition = addUidSection(1, "power", FLAG_FORMAT_AS_POWER | FLAG_OPTIONAL);
}
@@ -251,7 +276,7 @@
* Declares that the UID stats array has a section capturing EnergyConsumer data from
* PowerStatsService.
*/
- public void addUidSectionEnergyConsumers(int energyConsumerCount) {
+ protected void addUidSectionEnergyConsumers(int energyConsumerCount) {
mUidEnergyConsumerPosition = addUidSection(energyConsumerCount, "energy",
FLAG_OPTIONAL);
mUidEnergyConsumerCount = energyConsumerCount;
@@ -292,39 +317,6 @@
return stats[mUidPowerEstimatePosition] / MILLI_TO_NANO_MULTIPLIER;
}
- /**
- * Copies the elements of the stats array layout into <code>extras</code>
- */
- public void toExtras(PersistableBundle extras) {
- extras.putInt(EXTRA_DEVICE_DURATION_POSITION, mDeviceDurationPosition);
- extras.putInt(EXTRA_DEVICE_ENERGY_CONSUMERS_POSITION,
- mDeviceEnergyConsumerPosition);
- extras.putInt(EXTRA_DEVICE_ENERGY_CONSUMERS_COUNT,
- mDeviceEnergyConsumerCount);
- extras.putInt(EXTRA_DEVICE_POWER_POSITION, mDevicePowerEstimatePosition);
- extras.putInt(EXTRA_UID_DURATION_POSITION, mUidDurationPosition);
- extras.putInt(EXTRA_UID_ENERGY_CONSUMERS_POSITION, mUidEnergyConsumerPosition);
- extras.putInt(EXTRA_UID_ENERGY_CONSUMERS_COUNT, mUidEnergyConsumerCount);
- extras.putInt(EXTRA_UID_POWER_POSITION, mUidPowerEstimatePosition);
- extras.putString(PowerStats.Descriptor.EXTRA_DEVICE_STATS_FORMAT, mDeviceFormat.toString());
- extras.putString(PowerStats.Descriptor.EXTRA_STATE_STATS_FORMAT, mStateFormat.toString());
- extras.putString(PowerStats.Descriptor.EXTRA_UID_STATS_FORMAT, mUidFormat.toString());
- }
-
- /**
- * Retrieves elements of the stats array layout from <code>extras</code>
- */
- public void fromExtras(PersistableBundle extras) {
- mDeviceDurationPosition = extras.getInt(EXTRA_DEVICE_DURATION_POSITION);
- mDeviceEnergyConsumerPosition = extras.getInt(EXTRA_DEVICE_ENERGY_CONSUMERS_POSITION);
- mDeviceEnergyConsumerCount = extras.getInt(EXTRA_DEVICE_ENERGY_CONSUMERS_COUNT);
- mDevicePowerEstimatePosition = extras.getInt(EXTRA_DEVICE_POWER_POSITION);
- mUidDurationPosition = extras.getInt(EXTRA_UID_DURATION_POSITION);
- mUidEnergyConsumerPosition = extras.getInt(EXTRA_UID_ENERGY_CONSUMERS_POSITION);
- mUidEnergyConsumerCount = extras.getInt(EXTRA_UID_ENERGY_CONSUMERS_COUNT);
- mUidPowerEstimatePosition = extras.getInt(EXTRA_UID_POWER_POSITION);
- }
-
protected void putIntArray(PersistableBundle extras, String key, int[] array) {
if (array == null) {
return;
diff --git a/services/core/java/com/android/server/power/stats/ScreenPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/ScreenPowerStatsLayout.java
similarity index 89%
rename from services/core/java/com/android/server/power/stats/ScreenPowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/ScreenPowerStatsLayout.java
index f134aa8..6f6a7ff 100644
--- a/services/core/java/com/android/server/power/stats/ScreenPowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/ScreenPowerStatsLayout.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
import android.annotation.NonNull;
import android.os.BatteryStats;
@@ -41,14 +41,40 @@
private int mDeviceScreenDozePowerPosition;
private int mUidTopActivityTimePosition;
- ScreenPowerStatsLayout() {
+ public ScreenPowerStatsLayout(int energyConsumerCount, int displayCount) {
+ addDeviceScreenUsageDurationSection(displayCount);
+ addDeviceSectionEnergyConsumers(energyConsumerCount);
+ addDeviceSectionUsageDuration();
+ addDeviceSectionPowerEstimate();
+ addUidTopActivitiyDuration();
+ addUidSectionPowerEstimate();
}
- ScreenPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
+ public ScreenPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
super(descriptor);
+ PersistableBundle extras = descriptor.extras;
+ mDisplayCount = extras.getInt(EXTRA_DEVICE_SCREEN_COUNT, 1);
+ mDeviceScreenOnDurationPosition = extras.getInt(EXTRA_DEVICE_SCREEN_ON_DURATION_POSITION);
+ mDeviceBrightnessDurationPositions = extras.getIntArray(
+ EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS);
+ mDeviceScreenDozeDurationPosition = extras.getInt(EXTRA_DEVICE_DOZE_DURATION_POSITION);
+ mDeviceScreenDozePowerPosition = extras.getInt(EXTRA_DEVICE_DOZE_POWER_POSITION);
+ mUidTopActivityTimePosition = extras.getInt(EXTRA_UID_FOREGROUND_DURATION);
}
- void addDeviceScreenUsageDurationSection(int displayCount) {
+ @Override
+ public void toExtras(PersistableBundle extras) {
+ super.toExtras(extras);
+ extras.putInt(EXTRA_DEVICE_SCREEN_COUNT, mDisplayCount);
+ extras.putInt(EXTRA_DEVICE_SCREEN_ON_DURATION_POSITION, mDeviceScreenOnDurationPosition);
+ extras.putIntArray(EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS,
+ mDeviceBrightnessDurationPositions);
+ extras.putInt(EXTRA_DEVICE_DOZE_DURATION_POSITION, mDeviceScreenDozeDurationPosition);
+ extras.putInt(EXTRA_DEVICE_DOZE_POWER_POSITION, mDeviceScreenDozePowerPosition);
+ extras.putInt(EXTRA_UID_FOREGROUND_DURATION, mUidTopActivityTimePosition);
+ }
+
+ private void addDeviceScreenUsageDurationSection(int displayCount) {
mDisplayCount = displayCount;
mDeviceScreenOnDurationPosition = addDeviceSection(displayCount, "on");
mDeviceBrightnessDurationPositions = new int[BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS];
@@ -60,7 +86,7 @@
}
@Override
- public void addDeviceSectionPowerEstimate() {
+ protected void addDeviceSectionPowerEstimate() {
super.addDeviceSectionPowerEstimate();
// Used by AmbientDisplayPowerStatsProcessor
mDeviceScreenDozePowerPosition = addDeviceSection(1, "doze-power", FLAG_HIDDEN);
@@ -127,7 +153,7 @@
return stats[mDeviceScreenDozePowerPosition] / MILLI_TO_NANO_MULTIPLIER;
}
- void addUidTopActivitiyDuration() {
+ private void addUidTopActivitiyDuration() {
mUidTopActivityTimePosition = addUidSection(1, "top");
}
@@ -144,28 +170,4 @@
public long getUidTopActivityDuration(long[] stats) {
return stats[mUidTopActivityTimePosition];
}
-
- @Override
- public void toExtras(PersistableBundle extras) {
- super.toExtras(extras);
- extras.putInt(EXTRA_DEVICE_SCREEN_COUNT, mDisplayCount);
- extras.putInt(EXTRA_DEVICE_SCREEN_ON_DURATION_POSITION, mDeviceScreenOnDurationPosition);
- extras.putIntArray(EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS,
- mDeviceBrightnessDurationPositions);
- extras.putInt(EXTRA_DEVICE_DOZE_DURATION_POSITION, mDeviceScreenDozeDurationPosition);
- extras.putInt(EXTRA_DEVICE_DOZE_POWER_POSITION, mDeviceScreenDozePowerPosition);
- extras.putInt(EXTRA_UID_FOREGROUND_DURATION, mUidTopActivityTimePosition);
- }
-
- @Override
- public void fromExtras(PersistableBundle extras) {
- super.fromExtras(extras);
- mDisplayCount = extras.getInt(EXTRA_DEVICE_SCREEN_COUNT, 1);
- mDeviceScreenOnDurationPosition = extras.getInt(EXTRA_DEVICE_SCREEN_ON_DURATION_POSITION);
- mDeviceBrightnessDurationPositions = extras.getIntArray(
- EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS);
- mDeviceScreenDozeDurationPosition = extras.getInt(EXTRA_DEVICE_DOZE_DURATION_POSITION);
- mDeviceScreenDozePowerPosition = extras.getInt(EXTRA_DEVICE_DOZE_POWER_POSITION);
- mUidTopActivityTimePosition = extras.getInt(EXTRA_UID_FOREGROUND_DURATION);
- }
}
diff --git a/services/core/java/com/android/server/power/stats/SensorPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/SensorPowerStatsLayout.java
similarity index 72%
rename from services/core/java/com/android/server/power/stats/SensorPowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/SensorPowerStatsLayout.java
index e66cd39..e8df3dd 100644
--- a/services/core/java/com/android/server/power/stats/SensorPowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/SensorPowerStatsLayout.java
@@ -14,12 +14,17 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
import android.os.PersistableBundle;
import android.util.Slog;
import android.util.SparseIntArray;
+import com.android.internal.os.PowerStats;
+
+import java.util.Arrays;
+import java.util.Map;
+
public class SensorPowerStatsLayout extends PowerStatsLayout {
private static final String TAG = "SensorPowerStatsLayout";
private static final String EXTRA_DEVICE_SENSOR_HANDLES = "dsh";
@@ -27,7 +32,48 @@
private final SparseIntArray mSensorPositions = new SparseIntArray();
- void addUidSensorSection(int handle, String label) {
+ public SensorPowerStatsLayout(Map<Integer, String> idToLabelMap) {
+ Integer[] keys = new Integer[idToLabelMap.size()];
+ idToLabelMap.keySet().toArray(keys);
+ Arrays.sort(keys);
+ for (int i = 0; i < keys.length; i++) {
+ addUidSensorSection(keys[i], idToLabelMap.get(keys[i]));
+ }
+ addUidSectionPowerEstimate();
+ addDeviceSectionPowerEstimate();
+ }
+
+ public SensorPowerStatsLayout(PowerStats.Descriptor descriptor) {
+ super(descriptor);
+
+ PersistableBundle extras = descriptor.extras;
+ int[] handlers = extras.getIntArray(EXTRA_DEVICE_SENSOR_HANDLES);
+ int[] uidDurationPositions = extras.getIntArray(EXTRA_UID_SENSOR_POSITIONS);
+
+ if (handlers != null && uidDurationPositions != null) {
+ for (int i = 0; i < handlers.length; i++) {
+ mSensorPositions.put(handlers[i], uidDurationPositions[i]);
+ }
+ }
+ }
+
+ @Override
+ public void toExtras(PersistableBundle extras) {
+ super.toExtras(extras);
+
+ int[] handlers = new int[mSensorPositions.size()];
+ int[] uidDurationPositions = new int[mSensorPositions.size()];
+
+ for (int i = 0; i < mSensorPositions.size(); i++) {
+ handlers[i] = mSensorPositions.keyAt(i);
+ uidDurationPositions[i] = mSensorPositions.valueAt(i);
+ }
+
+ extras.putIntArray(EXTRA_DEVICE_SENSOR_HANDLES, handlers);
+ extras.putIntArray(EXTRA_UID_SENSOR_POSITIONS, uidDurationPositions);
+ }
+
+ private void addUidSensorSection(int handle, String label) {
mSensorPositions.put(handle, addUidSection(1, label, FLAG_OPTIONAL));
}
@@ -50,32 +96,4 @@
}
stats[position] += durationMs;
}
-
- @Override
- public void toExtras(PersistableBundle extras) {
- super.toExtras(extras);
-
- int[] handlers = new int[mSensorPositions.size()];
- int[] uidDurationPositions = new int[mSensorPositions.size()];
-
- for (int i = 0; i < mSensorPositions.size(); i++) {
- handlers[i] = mSensorPositions.keyAt(i);
- uidDurationPositions[i] = mSensorPositions.valueAt(i);
- }
-
- extras.putIntArray(EXTRA_DEVICE_SENSOR_HANDLES, handlers);
- extras.putIntArray(EXTRA_UID_SENSOR_POSITIONS, uidDurationPositions);
- }
-
- @Override
- public void fromExtras(PersistableBundle extras) {
- super.fromExtras(extras);
-
- int[] handlers = extras.getIntArray(EXTRA_DEVICE_SENSOR_HANDLES);
- int[] uidDurationPositions = extras.getIntArray(EXTRA_UID_SENSOR_POSITIONS);
-
- for (int i = 0; i < handlers.length; i++) {
- mSensorPositions.put(handlers[i], uidDurationPositions[i]);
- }
- }
}
diff --git a/services/core/java/com/android/server/power/stats/WifiPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/format/WifiPowerStatsLayout.java
similarity index 93%
rename from services/core/java/com/android/server/power/stats/WifiPowerStatsLayout.java
rename to services/core/java/com/android/server/power/stats/format/WifiPowerStatsLayout.java
index e2e8226..ce7ef12 100644
--- a/services/core/java/com/android/server/power/stats/WifiPowerStatsLayout.java
+++ b/services/core/java/com/android/server/power/stats/format/WifiPowerStatsLayout.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.format;
import android.annotation.NonNull;
import android.os.PersistableBundle;
@@ -22,7 +22,6 @@
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";
@@ -54,14 +53,56 @@
private int mUidScanTimePosition;
private int mUidBatchScanTimePosition;
- WifiPowerStatsLayout() {
+ public WifiPowerStatsLayout(int energyConsumerCount, boolean powerReportingSupported) {
+ addDeviceWifiActivity(powerReportingSupported);
+ addDeviceSectionEnergyConsumers(energyConsumerCount);
+ addUidNetworkStats();
+ addDeviceSectionUsageDuration();
+ addDeviceSectionPowerEstimate();
+ addUidSectionPowerEstimate();
}
- WifiPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
+ public WifiPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
super(descriptor);
+ PersistableBundle extras = descriptor.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);
}
- void addDeviceWifiActivity(boolean powerReportingSupported) {
+ /**
+ * 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);
+ }
+
+ private void addDeviceWifiActivity(boolean powerReportingSupported) {
mPowerReportingSupported = powerReportingSupported;
if (mPowerReportingSupported) {
mDeviceActiveTimePosition = UNSPECIFIED;
@@ -80,7 +121,7 @@
mDeviceBatchedScanTimePosition = addDeviceSection(1, "batched-scan", FLAG_OPTIONAL);
}
- void addUidNetworkStats() {
+ private void addUidNetworkStats() {
mUidRxPacketsPosition = addUidSection(1, "rx-pkts");
mUidRxBytesPosition = addUidSection(1, "rx-B");
mUidTxPacketsPosition = addUidSection(1, "tx-pkts");
@@ -196,46 +237,4 @@
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/AggregatedPowerStats.java b/services/core/java/com/android/server/power/stats/processor/AggregatedPowerStats.java
similarity index 97%
rename from services/core/java/com/android/server/power/stats/AggregatedPowerStats.java
rename to services/core/java/com/android/server/power/stats/processor/AggregatedPowerStats.java
index 674b4bc..a4758dd 100644
--- a/services/core/java/com/android/server/power/stats/AggregatedPowerStats.java
+++ b/services/core/java/com/android/server/power/stats/processor/AggregatedPowerStats.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import android.annotation.CurrentTimeMillisLong;
import android.annotation.DurationMillisLong;
@@ -33,7 +33,7 @@
import com.android.internal.os.PowerStats;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
-import com.android.server.power.stats.AggregatedPowerStatsConfig.PowerComponent;
+import com.android.server.power.stats.processor.AggregatedPowerStatsConfig.PowerComponent;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -143,7 +143,8 @@
}
}
- List<ClockUpdate> getClockUpdates() {
+ // TODO - DO NOT SUBMIT public
+ public List<ClockUpdate> getClockUpdates() {
return mClockUpdates;
}
@@ -274,7 +275,8 @@
int powerComponentId = parser.getAttributeInt(null,
PowerComponentAggregatedPowerStats.XML_ATTR_ID);
- PowerComponentAggregatedPowerStats powerComponentStats =
+ PowerComponentAggregatedPowerStats
+ powerComponentStats =
stats.getPowerComponentStats(powerComponentId);
if (powerComponentStats == null) {
PowerComponent powerComponent =
diff --git a/services/core/java/com/android/server/power/stats/AggregatedPowerStatsConfig.java b/services/core/java/com/android/server/power/stats/processor/AggregatedPowerStatsConfig.java
similarity index 95%
rename from services/core/java/com/android/server/power/stats/AggregatedPowerStatsConfig.java
rename to services/core/java/com/android/server/power/stats/processor/AggregatedPowerStatsConfig.java
index ec12228..eaeda43 100644
--- a/services/core/java/com/android/server/power/stats/AggregatedPowerStatsConfig.java
+++ b/services/core/java/com/android/server/power/stats/processor/AggregatedPowerStatsConfig.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -32,7 +32,7 @@
* WiFi, etc). Also, it determines which states are tracked globally and which ones on a per-UID
* basis.
*/
-public class AggregatedPowerStatsConfig {
+class AggregatedPowerStatsConfig {
public static final int STATE_POWER = 0;
public static final int STATE_SCREEN = 1;
public static final int STATE_PROCESS_STATE = 2;
@@ -70,7 +70,7 @@
/**
* Configuration for a give power component (CPU, WiFi, etc)
*/
- public static class PowerComponent {
+ static class PowerComponent {
private final int mPowerComponentId;
private @TrackedState int[] mTrackedDeviceStates;
private @TrackedState int[] mTrackedUidStates;
@@ -174,7 +174,7 @@
* standard power component IDs, e.g. {@link BatteryConsumer#POWER_COMPONENT_CPU}, or
* a custom power component.
*/
- public PowerComponent trackPowerComponent(int powerComponentId) {
+ PowerComponent trackPowerComponent(int powerComponentId) {
PowerComponent builder = new PowerComponent(powerComponentId);
mPowerComponents.add(builder);
return builder;
@@ -185,7 +185,7 @@
* of a different power component. The tracked states will be the same as the parent
* component's.
*/
- public PowerComponent trackPowerComponent(int powerComponentId,
+ PowerComponent trackPowerComponent(int powerComponentId,
int parentPowerComponentId) {
PowerComponent parent = null;
for (int i = 0; i < mPowerComponents.size(); i++) {
@@ -211,7 +211,7 @@
* Creates a configuration for custom power components, which are yet to be discovered
* dynamically through the integration with PowerStatsService.
*/
- public PowerComponent trackCustomPowerComponents(
+ PowerComponent trackCustomPowerComponents(
Supplier<PowerStatsProcessor> processorFactory) {
mCustomPowerStatsProcessorFactory = processorFactory;
mCustomPowerComponent = new PowerComponent(BatteryConsumer.POWER_COMPONENT_ANY);
@@ -221,7 +221,7 @@
/**
* Returns configurations for all registered or dynamically discovered power components.
*/
- public List<PowerComponent> getPowerComponentsAggregatedStatsConfigs() {
+ List<PowerComponent> getPowerComponentsAggregatedStatsConfigs() {
return mPowerComponents;
}
@@ -230,7 +230,7 @@
* integration with PowerStatsService.
*/
@Nullable
- public PowerComponent createPowerComponent(int powerComponentId) {
+ PowerComponent createPowerComponent(int powerComponentId) {
if (mCustomPowerComponent == null) {
return null;
}
diff --git a/services/core/java/com/android/server/power/stats/processor/AggregatedPowerStatsSection.java b/services/core/java/com/android/server/power/stats/processor/AggregatedPowerStatsSection.java
new file mode 100644
index 0000000..4a9730c
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/processor/AggregatedPowerStatsSection.java
@@ -0,0 +1,72 @@
+/*
+ * 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.server.power.stats.processor;
+
+import android.util.IndentingPrintWriter;
+
+import com.android.modules.utils.TypedXmlPullParser;
+import com.android.modules.utils.TypedXmlSerializer;
+import com.android.server.power.stats.PowerStatsSpan;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+class AggregatedPowerStatsSection extends PowerStatsSpan.Section {
+ public static final String TYPE = "aggregated-power-stats";
+
+ private final AggregatedPowerStats mAggregatedPowerStats;
+
+ AggregatedPowerStatsSection(AggregatedPowerStats aggregatedPowerStats) {
+ super(TYPE);
+ mAggregatedPowerStats = aggregatedPowerStats;
+ }
+
+ public AggregatedPowerStats getAggregatedPowerStats() {
+ return mAggregatedPowerStats;
+ }
+
+ @Override
+ public void write(TypedXmlSerializer serializer) throws IOException {
+ mAggregatedPowerStats.writeXml(serializer);
+ }
+
+ @Override
+ public void dump(IndentingPrintWriter ipw) {
+ mAggregatedPowerStats.dump(ipw);
+ }
+
+ static class Reader implements PowerStatsSpan.SectionReader {
+ private final AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
+
+ Reader(AggregatedPowerStatsConfig config) {
+ mAggregatedPowerStatsConfig = config;
+ }
+
+ @Override
+ public String getType() {
+ return TYPE;
+ }
+
+ @Override
+ public PowerStatsSpan.Section read(String sectionType, TypedXmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ return new AggregatedPowerStatsSection(
+ AggregatedPowerStats.createFromXml(parser, mAggregatedPowerStatsConfig));
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/power/stats/AmbientDisplayPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java
similarity index 86%
rename from services/core/java/com/android/server/power/stats/AmbientDisplayPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java
index a42929f..32dfdf9 100644
--- a/services/core/java/com/android/server/power/stats/AmbientDisplayPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java
@@ -13,24 +13,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import android.os.BatteryConsumer;
import android.os.PersistableBundle;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.AmbientDisplayPowerStatsLayout;
+import com.android.server.power.stats.format.ScreenPowerStatsLayout;
-public class AmbientDisplayPowerStatsProcessor extends PowerStatsProcessor {
- private final PowerStatsLayout mStatsLayout;
+class AmbientDisplayPowerStatsProcessor extends PowerStatsProcessor {
+ private final AmbientDisplayPowerStatsLayout mStatsLayout;
private final PowerStats.Descriptor mDescriptor;
private final long[] mTmpDeviceStats;
private PowerStats.Descriptor mScreenPowerStatsDescriptor;
private ScreenPowerStatsLayout mScreenPowerStatsLayout;
private long[] mTmpScreenStats;
- public AmbientDisplayPowerStatsProcessor() {
- mStatsLayout = new PowerStatsLayout();
- mStatsLayout.addDeviceSectionPowerEstimate();
+ AmbientDisplayPowerStatsProcessor() {
+ mStatsLayout = new AmbientDisplayPowerStatsLayout();
PersistableBundle extras = new PersistableBundle();
mStatsLayout.toExtras(extras);
mDescriptor = new PowerStats.Descriptor(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY,
diff --git a/services/core/java/com/android/server/power/stats/AudioPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/AudioPowerStatsProcessor.java
similarity index 82%
rename from services/core/java/com/android/server/power/stats/AudioPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/AudioPowerStatsProcessor.java
index a48f162..ad1b4a7 100644
--- a/services/core/java/com/android/server/power/stats/AudioPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/AudioPowerStatsProcessor.java
@@ -14,15 +14,16 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import com.android.internal.os.PowerProfile;
+import com.android.server.power.stats.PowerStatsUidResolver;
-public class AudioPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
- public AudioPowerStatsProcessor(PowerProfile powerProfile,
+class AudioPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
+ AudioPowerStatsProcessor(PowerProfile powerProfile,
PowerStatsUidResolver uidResolver) {
super(BatteryConsumer.POWER_COMPONENT_AUDIO, uidResolver,
powerProfile.getAveragePower(PowerProfile.POWER_AUDIO));
diff --git a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessor.java
similarity index 97%
rename from services/core/java/com/android/server/power/stats/BinaryStatePowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessor.java
index 03df46a..e45a707 100644
--- a/services/core/java/com/android/server/power/stats/BinaryStatePowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessor.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import android.annotation.IntDef;
import android.os.BatteryStats;
@@ -22,6 +22,9 @@
import android.os.Process;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.UsageBasedPowerEstimator;
+import com.android.server.power.stats.format.BinaryStatePowerStatsLayout;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/services/core/java/com/android/server/power/stats/BluetoothPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/BluetoothPowerStatsProcessor.java
similarity index 97%
rename from services/core/java/com/android/server/power/stats/BluetoothPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/BluetoothPowerStatsProcessor.java
index 077b057..4c1a0db 100644
--- a/services/core/java/com/android/server/power/stats/BluetoothPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/BluetoothPowerStatsProcessor.java
@@ -14,17 +14,17 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.UsageBasedPowerEstimator;
+import com.android.server.power.stats.format.BluetoothPowerStatsLayout;
import java.util.ArrayList;
import java.util.List;
-public class BluetoothPowerStatsProcessor extends PowerStatsProcessor {
- private static final String TAG = "BluetoothPowerStatsProcessor";
-
+class BluetoothPowerStatsProcessor extends PowerStatsProcessor {
private final UsageBasedPowerEstimator mRxPowerEstimator;
private final UsageBasedPowerEstimator mTxPowerEstimator;
private final UsageBasedPowerEstimator mIdlePowerEstimator;
@@ -37,7 +37,7 @@
private long[] mTmpDeviceStatsArray;
private long[] mTmpUidStatsArray;
- public BluetoothPowerStatsProcessor(PowerProfile powerProfile) {
+ BluetoothPowerStatsProcessor(PowerProfile powerProfile) {
mRxPowerEstimator = new UsageBasedPowerEstimator(
powerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_RX));
mTxPowerEstimator = new UsageBasedPowerEstimator(
diff --git a/services/core/java/com/android/server/power/stats/CameraPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/CameraPowerStatsProcessor.java
similarity index 82%
rename from services/core/java/com/android/server/power/stats/CameraPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/CameraPowerStatsProcessor.java
index 15c3eb8..8309061 100644
--- a/services/core/java/com/android/server/power/stats/CameraPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/CameraPowerStatsProcessor.java
@@ -14,15 +14,16 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import com.android.internal.os.PowerProfile;
+import com.android.server.power.stats.PowerStatsUidResolver;
-public class CameraPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
- public CameraPowerStatsProcessor(PowerProfile powerProfile,
+class CameraPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
+ CameraPowerStatsProcessor(PowerProfile powerProfile,
PowerStatsUidResolver uidResolver) {
super(BatteryConsumer.POWER_COMPONENT_CAMERA, uidResolver,
powerProfile.getAveragePower(PowerProfile.POWER_CAMERA));
diff --git a/services/core/java/com/android/server/power/stats/CpuPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/CpuPowerStatsProcessor.java
similarity index 97%
rename from services/core/java/com/android/server/power/stats/CpuPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/CpuPowerStatsProcessor.java
index 6da0a8f..5f7a3da 100644
--- a/services/core/java/com/android/server/power/stats/CpuPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/CpuPowerStatsProcessor.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import android.util.ArraySet;
import android.util.Log;
@@ -22,13 +22,14 @@
import com.android.internal.os.CpuScalingPolicies;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.CpuPowerStatsLayout;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
-public class CpuPowerStatsProcessor extends PowerStatsProcessor {
+class CpuPowerStatsProcessor extends PowerStatsProcessor {
private static final String TAG = "CpuPowerStatsProcessor";
private static final double HOUR_IN_MILLIS = TimeUnit.HOURS.toMillis(1);
@@ -72,7 +73,7 @@
// Temp array for retrieval of UID power stats, to avoid repeated allocations
private long[] mTmpUidStatsArray;
- public CpuPowerStatsProcessor(PowerProfile powerProfile, CpuScalingPolicies scalingPolicies) {
+ CpuPowerStatsProcessor(PowerProfile powerProfile, CpuScalingPolicies scalingPolicies) {
mCpuScalingPolicies = scalingPolicies;
mCpuScalingStepCount = scalingPolicies.getScalingStepCount();
mScalingStepToCluster = new int[mCpuScalingStepCount];
@@ -104,8 +105,7 @@
}
mLastUsedDescriptor = descriptor;
- mStatsLayout = new CpuPowerStatsLayout();
- mStatsLayout.fromExtras(descriptor.extras);
+ mStatsLayout = new CpuPowerStatsLayout(descriptor);
mTmpDeviceStatsArray = new long[descriptor.statsArrayLength];
mTmpUidStatsArray = new long[descriptor.uidStatsArrayLength];
@@ -138,7 +138,7 @@
}
@Override
- public void finish(PowerComponentAggregatedPowerStats stats, long timestampMs) {
+ void finish(PowerComponentAggregatedPowerStats stats, long timestampMs) {
if (stats.getPowerStatsDescriptor() == null) {
return;
}
diff --git a/services/core/java/com/android/server/power/stats/CustomEnergyConsumerPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsProcessor.java
similarity index 94%
rename from services/core/java/com/android/server/power/stats/CustomEnergyConsumerPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsProcessor.java
index a86242a..76adc47 100644
--- a/services/core/java/com/android/server/power/stats/CustomEnergyConsumerPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsProcessor.java
@@ -14,14 +14,15 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.EnergyConsumerPowerStatsLayout;
import java.util.ArrayList;
import java.util.List;
-public class CustomEnergyConsumerPowerStatsProcessor extends PowerStatsProcessor {
+class CustomEnergyConsumerPowerStatsProcessor extends PowerStatsProcessor {
private static final EnergyConsumerPowerStatsLayout sLayout =
new EnergyConsumerPowerStatsLayout();
private long[] mTmpDeviceStatsArray;
diff --git a/services/core/java/com/android/server/power/stats/FlashlightPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/FlashlightPowerStatsProcessor.java
similarity index 82%
rename from services/core/java/com/android/server/power/stats/FlashlightPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/FlashlightPowerStatsProcessor.java
index f7216c9..b0bef69 100644
--- a/services/core/java/com/android/server/power/stats/FlashlightPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/FlashlightPowerStatsProcessor.java
@@ -14,15 +14,16 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import com.android.internal.os.PowerProfile;
+import com.android.server.power.stats.PowerStatsUidResolver;
-public class FlashlightPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
- public FlashlightPowerStatsProcessor(PowerProfile powerProfile,
+class FlashlightPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
+ FlashlightPowerStatsProcessor(PowerProfile powerProfile,
PowerStatsUidResolver uidResolver) {
super(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT, uidResolver,
powerProfile.getAveragePower(PowerProfile.POWER_FLASHLIGHT));
diff --git a/services/core/java/com/android/server/power/stats/GnssPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/GnssPowerStatsProcessor.java
similarity index 94%
rename from services/core/java/com/android/server/power/stats/GnssPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/GnssPowerStatsProcessor.java
index 0b28710..f1e3e90 100644
--- a/services/core/java/com/android/server/power/stats/GnssPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/GnssPowerStatsProcessor.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import android.location.GnssSignalQuality;
import android.os.BatteryConsumer;
@@ -23,10 +23,13 @@
import com.android.internal.os.PowerProfile;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.UsageBasedPowerEstimator;
+import com.android.server.power.stats.format.GnssPowerStatsLayout;
import java.util.Arrays;
-public class GnssPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
+class GnssPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
private static final GnssPowerStatsLayout sStatsLayout = new GnssPowerStatsLayout();
private final UsageBasedPowerEstimator[] mSignalLevelEstimators =
new UsageBasedPowerEstimator[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS];
@@ -37,7 +40,7 @@
private final long[] mGnssSignalDurations =
new long[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS];
- public GnssPowerStatsProcessor(PowerProfile powerProfile, PowerStatsUidResolver uidResolver) {
+ GnssPowerStatsProcessor(PowerProfile powerProfile, PowerStatsUidResolver uidResolver) {
super(BatteryConsumer.POWER_COMPONENT_GNSS, uidResolver,
powerProfile.getAveragePower(PowerProfile.POWER_GPS_ON),
sStatsLayout);
diff --git a/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessor.java
similarity index 96%
rename from services/core/java/com/android/server/power/stats/MobileRadioPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessor.java
index dcce562..b4c40de8 100644
--- a/services/core/java/com/android/server/power/stats/MobileRadioPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessor.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import android.os.BatteryStats;
import android.telephony.CellSignalStrength;
@@ -26,13 +26,15 @@
import com.android.internal.os.PowerProfile;
import com.android.internal.os.PowerStats;
import com.android.internal.power.ModemPowerProfile;
+import com.android.server.power.stats.UsageBasedPowerEstimator;
+import com.android.server.power.stats.format.MobileRadioPowerStatsLayout;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-public class MobileRadioPowerStatsProcessor extends PowerStatsProcessor {
- private static final String TAG = "MobileRadioPowerStatsProcessor";
+class MobileRadioPowerStatsProcessor extends PowerStatsProcessor {
+ private static final String TAG = "MobileRadioPowerStats";
private static final boolean DEBUG = false;
private static final int NUM_SIGNAL_STRENGTH_LEVELS =
@@ -61,7 +63,7 @@
private long[] mTmpStateStatsArray;
private long[] mTmpUidStatsArray;
- public MobileRadioPowerStatsProcessor(PowerProfile powerProfile) {
+ MobileRadioPowerStatsProcessor(PowerProfile powerProfile) {
final double sleepDrainRateMa = powerProfile.getAverageBatteryDrainOrDefaultMa(
PowerProfile.SUBSYSTEM_MODEM | ModemPowerProfile.MODEM_DRAIN_TYPE_SLEEP,
Double.NaN);
@@ -101,7 +103,7 @@
? ServiceState.FREQUENCY_RANGE_COUNT : 1;
for (int freqRange = 0; freqRange < freqCount; freqRange++) {
mRxTxPowerEstimators.put(
- MobileRadioPowerStatsCollector.makeStateKey(rat, freqRange),
+ MobileRadioPowerStatsLayout.makeStateKey(rat, freqRange),
buildRxTxPowerEstimators(powerProfile, rat, freqRange));
}
}
@@ -114,8 +116,7 @@
ModemPowerProfile.MODEM_DRAIN_TYPE_RX, rat, freqRange, IGNORE);
double rxDrainRateMa = powerProfile.getAverageBatteryDrainOrDefaultMa(rxKey, Double.NaN);
if (Double.isNaN(rxDrainRateMa)) {
- Log.w(TAG, "Unavailable Power Profile constant for key 0x"
- + Long.toHexString(rxKey));
+ Log.w(TAG, "Unavailable Power Profile constant for key 0x" + Long.toHexString(rxKey));
rxDrainRateMa = 0;
}
estimators.mRxPowerEstimator = new UsageBasedPowerEstimator(rxDrainRateMa);
diff --git a/services/core/java/com/android/server/power/stats/processor/MultiStatePowerAttributor.java b/services/core/java/com/android/server/power/stats/processor/MultiStatePowerAttributor.java
new file mode 100644
index 0000000..2ba4a52
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/processor/MultiStatePowerAttributor.java
@@ -0,0 +1,310 @@
+/*
+ * 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.processor;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.hardware.SensorManager;
+import android.os.BatteryConsumer;
+import android.os.BatteryUsageStats;
+import android.util.IndentingPrintWriter;
+import android.util.Slog;
+import android.util.SparseBooleanArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BatteryStatsHistory;
+import com.android.internal.os.CpuScalingPolicies;
+import com.android.internal.os.PowerProfile;
+import com.android.server.power.stats.PowerAttributor;
+import com.android.server.power.stats.PowerStatsSpan;
+import com.android.server.power.stats.PowerStatsStore;
+import com.android.server.power.stats.PowerStatsUidResolver;
+
+import java.util.List;
+
+public class MultiStatePowerAttributor implements PowerAttributor {
+ private static final String TAG = "MultiStatePowerAttributor";
+
+ private final PowerStatsStore mPowerStatsStore;
+ private final PowerStatsExporter mPowerStatsExporter;
+ private final PowerStatsAggregator mPowerStatsAggregator;
+ private final SparseBooleanArray mPowerStatsExporterEnabled = new SparseBooleanArray();
+
+ // TODO(b/346371828): remove dependency on PowerStatsUidResolver. At the time of power
+ // attribution isolates UIDs are supposed to be long forgotten.
+ public MultiStatePowerAttributor(Context context, PowerStatsStore powerStatsStore,
+ @NonNull PowerProfile powerProfile, @NonNull CpuScalingPolicies cpuScalingPolicies,
+ @NonNull PowerStatsUidResolver powerStatsUidResolver) {
+ this(powerStatsStore, new PowerStatsAggregator(
+ createAggregatedPowerStatsConfig(context, powerProfile, cpuScalingPolicies,
+ powerStatsUidResolver)));
+ }
+
+ @VisibleForTesting
+ MultiStatePowerAttributor(PowerStatsStore powerStatsStore,
+ PowerStatsAggregator powerStatsAggregator) {
+ mPowerStatsStore = powerStatsStore;
+ mPowerStatsAggregator = powerStatsAggregator;
+ mPowerStatsStore.addSectionReader(
+ new AggregatedPowerStatsSection.Reader(mPowerStatsAggregator.getConfig()));
+ mPowerStatsExporter = new PowerStatsExporter(mPowerStatsStore, mPowerStatsAggregator);
+ }
+
+ private static AggregatedPowerStatsConfig createAggregatedPowerStatsConfig(Context context,
+ PowerProfile powerProfile, CpuScalingPolicies cpuScalingPolicies,
+ PowerStatsUidResolver powerStatsUidResolver) {
+ AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_CPU)
+ .trackDeviceStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN)
+ .trackUidStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN,
+ AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+ .setProcessorSupplier(
+ () -> new CpuPowerStatsProcessor(powerProfile, cpuScalingPolicies));
+
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_SCREEN)
+ .trackDeviceStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN)
+ .trackUidStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN)
+ .setProcessorSupplier(
+ () -> new ScreenPowerStatsProcessor(powerProfile));
+
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY,
+ BatteryConsumer.POWER_COMPONENT_SCREEN)
+ .setProcessorSupplier(AmbientDisplayPowerStatsProcessor::new);
+
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
+ .trackDeviceStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN)
+ .trackUidStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN,
+ AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+ .setProcessorSupplier(
+ () -> new MobileRadioPowerStatsProcessor(powerProfile));
+
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_PHONE,
+ BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
+ .setProcessorSupplier(PhoneCallPowerStatsProcessor::new);
+
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_WIFI)
+ .trackDeviceStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN)
+ .trackUidStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN,
+ AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+ .setProcessorSupplier(
+ () -> new WifiPowerStatsProcessor(powerProfile));
+
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_BLUETOOTH)
+ .trackDeviceStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN)
+ .trackUidStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN,
+ AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+ .setProcessorSupplier(
+ () -> new BluetoothPowerStatsProcessor(powerProfile));
+
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_AUDIO)
+ .trackDeviceStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN)
+ .trackUidStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN,
+ AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+ .setProcessorSupplier(
+ () -> new AudioPowerStatsProcessor(powerProfile, powerStatsUidResolver));
+
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_VIDEO)
+ .trackDeviceStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN)
+ .trackUidStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN,
+ AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+ .setProcessorSupplier(
+ () -> new VideoPowerStatsProcessor(powerProfile, powerStatsUidResolver));
+
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT)
+ .trackDeviceStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN)
+ .trackUidStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN,
+ AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+ .setProcessorSupplier(
+ () -> new FlashlightPowerStatsProcessor(powerProfile,
+ powerStatsUidResolver));
+
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_CAMERA)
+ .trackDeviceStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN)
+ .trackUidStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN,
+ AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+ .setProcessorSupplier(
+ () -> new CameraPowerStatsProcessor(powerProfile, powerStatsUidResolver));
+
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_GNSS)
+ .trackDeviceStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN)
+ .trackUidStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN,
+ AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+ .setProcessorSupplier(
+ () -> new GnssPowerStatsProcessor(powerProfile, powerStatsUidResolver));
+
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_SENSORS)
+ .trackDeviceStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN)
+ .trackUidStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN,
+ AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+ .setProcessorSupplier(() -> new SensorPowerStatsProcessor(
+ () -> context.getSystemService(SensorManager.class)));
+
+ config.trackCustomPowerComponents(CustomEnergyConsumerPowerStatsProcessor::new)
+ .trackDeviceStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN)
+ .trackUidStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN,
+ AggregatedPowerStatsConfig.STATE_PROCESS_STATE);
+ return config;
+ }
+
+ /**
+ * Marks the specified power component as supported by this PowerAttributor
+ */
+ public void setPowerComponentSupported(@BatteryConsumer.PowerComponentId int powerComponentId,
+ boolean enabled) {
+ mPowerStatsExporterEnabled.put(powerComponentId, enabled);
+ mPowerStatsExporter.setPowerComponentEnabled(powerComponentId, enabled);
+ }
+
+ @Override
+ public boolean isPowerComponentSupported(
+ @BatteryConsumer.PowerComponentId int powerComponentId) {
+ return mPowerStatsExporterEnabled.get(powerComponentId);
+ }
+
+ @Override
+ public void estimatePowerConsumption(BatteryUsageStats.Builder batteryUsageStatsBuilder,
+ BatteryStatsHistory batteryHistory, long monotonicStartTime, long monotonicEndTime) {
+ mPowerStatsExporter.exportAggregatedPowerStats(batteryUsageStatsBuilder, batteryHistory,
+ monotonicStartTime, monotonicEndTime);
+ }
+
+ @Override
+ public void dumpEstimatedPowerConsumption(IndentingPrintWriter ipw,
+ BatteryStatsHistory batteryStatsHistory,
+ long startTime, long endTime) {
+ mPowerStatsAggregator.aggregatePowerStats(batteryStatsHistory, startTime, endTime,
+ stats -> {
+ // Create a PowerStatsSpan for consistency of the textual output
+ PowerStatsSpan span = createPowerStatsSpan(stats);
+ if (span != null) {
+ span.dump(ipw);
+ }
+ });
+ }
+
+ @Override
+ public long storeEstimatedPowerConsumption(BatteryStatsHistory batteryStatsHistory,
+ long startTime, long endTimeMs) {
+ long[] lastSavedMonotonicTime = new long[1];
+ mPowerStatsAggregator.aggregatePowerStats(batteryStatsHistory, startTime, endTimeMs,
+ stats -> {
+ storeAggregatedPowerStats(stats);
+ lastSavedMonotonicTime[0] = stats.getStartTime() + stats.getDuration();
+ });
+ return lastSavedMonotonicTime[0];
+ }
+
+ @VisibleForTesting
+ void storeAggregatedPowerStats(AggregatedPowerStats stats) {
+ PowerStatsSpan span = createPowerStatsSpan(stats);
+ if (span == null) {
+ return;
+ }
+ mPowerStatsStore.storePowerStatsSpan(span);
+ }
+
+ private static PowerStatsSpan createPowerStatsSpan(AggregatedPowerStats stats) {
+ List<AggregatedPowerStats.ClockUpdate> clockUpdates = stats.getClockUpdates();
+ if (clockUpdates.isEmpty()) {
+ Slog.w(TAG, "No clock updates in aggregated power stats " + stats);
+ return null;
+ }
+
+ long monotonicTime = clockUpdates.get(0).monotonicTime;
+ long durationSum = 0;
+ PowerStatsSpan span = new PowerStatsSpan(monotonicTime);
+ for (int i = 0; i < clockUpdates.size(); i++) {
+ AggregatedPowerStats.ClockUpdate clockUpdate = clockUpdates.get(i);
+ long duration;
+ if (i == clockUpdates.size() - 1) {
+ duration = stats.getDuration() - durationSum;
+ } else {
+ duration = clockUpdate.monotonicTime - monotonicTime;
+ }
+ span.addTimeFrame(clockUpdate.monotonicTime, clockUpdate.currentTime, duration);
+ monotonicTime = clockUpdate.monotonicTime;
+ durationSum += duration;
+ }
+
+ span.addSection(new AggregatedPowerStatsSection(stats));
+ return span;
+ }
+
+ @Override
+ public long getLastSavedEstimatesPowerConsumptionTimestamp() {
+ long timestamp = -1;
+ for (PowerStatsSpan.Metadata metadata : mPowerStatsStore.getTableOfContents()) {
+ if (metadata.getSections().contains(AggregatedPowerStatsSection.TYPE)) {
+ for (PowerStatsSpan.TimeFrame timeFrame : metadata.getTimeFrames()) {
+ long endMonotonicTime = timeFrame.startMonotonicTime + timeFrame.duration;
+ if (endMonotonicTime > timestamp) {
+ timestamp = endMonotonicTime;
+ }
+ }
+ }
+ }
+ return timestamp;
+ }
+}
diff --git a/services/core/java/com/android/server/power/stats/MultiStateStats.java b/services/core/java/com/android/server/power/stats/processor/MultiStateStats.java
similarity index 94%
rename from services/core/java/com/android/server/power/stats/MultiStateStats.java
rename to services/core/java/com/android/server/power/stats/processor/MultiStateStats.java
index c3a0aeb..28474a5 100644
--- a/services/core/java/com/android/server/power/stats/MultiStateStats.java
+++ b/services/core/java/com/android/server/power/stats/processor/MultiStateStats.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import android.util.Slog;
@@ -37,7 +37,7 @@
* CPU residency, Network packet counts etc. All metrics must be represented as <code>long</code>
* values;
*/
-public class MultiStateStats {
+class MultiStateStats {
private static final String TAG = "MultiStateStats";
private static final String XML_TAG_STATS = "stats";
@@ -47,12 +47,12 @@
* A set of states, e.g. on-battery, screen-on, procstate. The state values are integers
* from 0 to States.mLabels.length
*/
- public static class States {
+ static class States {
final String mName;
final boolean mTracked;
final String[] mLabels;
- public States(String name, boolean tracked, String... labels) {
+ States(String name, boolean tracked, String... labels) {
mName = name;
mTracked = tracked;
mLabels = labels;
@@ -121,7 +121,7 @@
* Factory for MultiStateStats containers. All generated containers retain their connection
* to the Factory and the corresponding configuration.
*/
- public static class Factory {
+ static class Factory {
private static final int INVALID_SERIAL_STATE = -1;
final int mDimensionCount;
final States[] mStates;
@@ -147,7 +147,7 @@
final int[] mCompositeToSerialState;
final int mSerialStateCount;
- public Factory(int dimensionCount, States... states) {
+ Factory(int dimensionCount, States... states) {
mDimensionCount = dimensionCount;
mStates = states;
@@ -250,7 +250,7 @@
/**
* Allocates a new stats container using this Factory's configuration.
*/
- public MultiStateStats create() {
+ MultiStateStats create() {
return new MultiStateStats(this, mDimensionCount);
}
@@ -293,16 +293,16 @@
private int mCompositeState;
private boolean mTracking;
- public MultiStateStats(Factory factory, int dimensionCount) {
+ MultiStateStats(Factory factory, int dimensionCount) {
this.mFactory = factory;
mCounter = new LongArrayMultiStateCounter(factory.mSerialStateCount, dimensionCount);
}
- public int getDimensionCount() {
+ int getDimensionCount() {
return mFactory.mDimensionCount;
}
- public States[] getStates() {
+ States[] getStates() {
return mFactory.mStates;
}
@@ -310,7 +310,7 @@
* Copies time-in-state and timestamps from the supplied prototype. Does not
* copy accumulated counts.
*/
- public void copyStatesFrom(MultiStateStats otherStats) {
+ void copyStatesFrom(MultiStateStats otherStats) {
mCounter.copyStatesFrom(otherStats.mCounter);
}
@@ -322,7 +322,7 @@
* @param state The new value of the state (e.g. 0 or 1 for "on-battery")
* @param timestampMs The time when the state change occurred
*/
- public void setState(int stateIndex, int state, long timestampMs) {
+ void setState(int stateIndex, int state, long timestampMs) {
if (!mTracking) {
mCounter.updateValues(new long[mCounter.getArrayLength()], timestampMs);
mTracking = true;
@@ -335,7 +335,7 @@
* Adds the delta to the metrics. The number of values must correspond to the dimension count
* supplied to the Factory constructor
*/
- public void increment(long[] values, long timestampMs) {
+ void increment(long[] values, long timestampMs) {
mCounter.incrementValues(values, timestampMs);
mTracking = true;
}
@@ -343,21 +343,21 @@
/**
* Returns accumulated stats for the specified composite state.
*/
- public void getStats(long[] outValues, int[] states) {
+ void getStats(long[] outValues, int[] states) {
mCounter.getCounts(outValues, mFactory.getSerialState(states));
}
/**
* Updates the stats values for the provided combination of states.
*/
- public void setStats(int[] states, long[] values) {
+ void setStats(int[] states, long[] values) {
mCounter.setValues(mFactory.getSerialState(states), values);
}
/**
* Resets the counters.
*/
- public void reset() {
+ void reset() {
mCounter.reset();
mTracking = false;
}
@@ -365,7 +365,7 @@
/**
* Stores contents in an XML doc.
*/
- public void writeXml(TypedXmlSerializer serializer) throws IOException {
+ void writeXml(TypedXmlSerializer serializer) throws IOException {
long[] tmpArray = new long[mCounter.getArrayLength()];
try {
@@ -420,8 +420,7 @@
* Populates the object with contents in an XML doc. The parser is expected to be
* positioned on the opening tag of the corresponding element.
*/
- public boolean readFromXml(TypedXmlPullParser parser) throws XmlPullParserException,
- IOException {
+ boolean readFromXml(TypedXmlPullParser parser) throws XmlPullParserException, IOException {
String outerTag = parser.getName();
long[] tmpArray = new long[mCounter.getArrayLength()];
int eventType = parser.getEventType();
diff --git a/services/core/java/com/android/server/power/stats/PhoneCallPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessor.java
similarity index 88%
rename from services/core/java/com/android/server/power/stats/PhoneCallPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessor.java
index ec23fa0..3957ae0 100644
--- a/services/core/java/com/android/server/power/stats/PhoneCallPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessor.java
@@ -13,24 +13,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import android.os.BatteryConsumer;
import android.os.PersistableBundle;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.MobileRadioPowerStatsLayout;
+import com.android.server.power.stats.format.PhoneCallPowerStatsLayout;
-public class PhoneCallPowerStatsProcessor extends PowerStatsProcessor {
- private final PowerStatsLayout mStatsLayout;
+class PhoneCallPowerStatsProcessor extends PowerStatsProcessor {
+ private final PhoneCallPowerStatsLayout mStatsLayout;
private final PowerStats.Descriptor mDescriptor;
private final long[] mTmpDeviceStats;
private PowerStats.Descriptor mMobileRadioStatsDescriptor;
private MobileRadioPowerStatsLayout mMobileRadioStatsLayout;
private long[] mTmpMobileRadioDeviceStats;
- public PhoneCallPowerStatsProcessor() {
- mStatsLayout = new PowerStatsLayout();
- mStatsLayout.addDeviceSectionPowerEstimate();
+ PhoneCallPowerStatsProcessor() {
+ mStatsLayout = new PhoneCallPowerStatsLayout();
PersistableBundle extras = new PersistableBundle();
mStatsLayout.toExtras(extras);
mDescriptor = new PowerStats.Descriptor(BatteryConsumer.POWER_COMPONENT_PHONE,
diff --git a/services/core/java/com/android/server/power/stats/PowerComponentAggregatedPowerStats.java b/services/core/java/com/android/server/power/stats/processor/PowerComponentAggregatedPowerStats.java
similarity index 98%
rename from services/core/java/com/android/server/power/stats/PowerComponentAggregatedPowerStats.java
rename to services/core/java/com/android/server/power/stats/processor/PowerComponentAggregatedPowerStats.java
index a92a6fd3..d04c5ba 100644
--- a/services/core/java/com/android/server/power/stats/PowerComponentAggregatedPowerStats.java
+++ b/services/core/java/com/android/server/power/stats/processor/PowerComponentAggregatedPowerStats.java
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
-
-import static com.android.server.power.stats.MultiStateStats.STATE_DOES_NOT_EXIST;
+package com.android.server.power.stats.processor;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -147,7 +145,8 @@
int uidStateId = MultiStateStats.States
.findTrackedStateByName(mUidStateConfig, mDeviceStateConfig[stateId].getName());
- if (uidStateId != STATE_DOES_NOT_EXIST && mUidStateConfig[uidStateId].isTracked()) {
+ if (uidStateId != MultiStateStats.STATE_DOES_NOT_EXIST
+ && mUidStateConfig[uidStateId].isTracked()) {
for (int i = mUidStats.size() - 1; i >= 0; i--) {
PowerComponentAggregatedPowerStats.UidStats uidStats = mUidStats.valueAt(i);
if (uidStats.stats == null) {
@@ -271,7 +270,7 @@
if (mUidStateConfig[stateId].isTracked()) {
int deviceStateId = MultiStateStats.States.findTrackedStateByName(
mDeviceStateConfig, mUidStateConfig[stateId].getName());
- if (deviceStateId != STATE_DOES_NOT_EXIST
+ if (deviceStateId != MultiStateStats.STATE_DOES_NOT_EXIST
&& mDeviceStateConfig[deviceStateId].isTracked()) {
uidStats.states[stateId] = mDeviceStates[deviceStateId];
}
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java b/services/core/java/com/android/server/power/stats/processor/PowerStatsAggregator.java
similarity index 92%
rename from services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
rename to services/core/java/com/android/server/power/stats/processor/PowerStatsAggregator.java
index c734f68..32c1056 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsAggregator.java
+++ b/services/core/java/com/android/server/power/stats/processor/PowerStatsAggregator.java
@@ -13,13 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import android.annotation.NonNull;
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.util.SparseBooleanArray;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BatteryStatsHistory;
import com.android.internal.os.BatteryStatsHistoryIterator;
@@ -33,20 +34,22 @@
public class PowerStatsAggregator {
private static final long UNINITIALIZED = -1;
private final AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
- private final BatteryStatsHistory mHistory;
private final SparseBooleanArray mEnabledComponents =
new SparseBooleanArray(BatteryConsumer.POWER_COMPONENT_COUNT + 10);
private AggregatedPowerStats mStats;
private int mCurrentBatteryState = AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
private int mCurrentScreenState = AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
- public PowerStatsAggregator(@NonNull AggregatedPowerStatsConfig aggregatedPowerStatsConfig,
- @NonNull BatteryStatsHistory history) {
- mAggregatedPowerStatsConfig = aggregatedPowerStatsConfig;
- mHistory = history;
+ @VisibleForTesting
+ public PowerStatsAggregator() {
+ this(new AggregatedPowerStatsConfig());
}
- public AggregatedPowerStatsConfig getConfig() {
+ PowerStatsAggregator(@NonNull AggregatedPowerStatsConfig aggregatedPowerStatsConfig) {
+ mAggregatedPowerStatsConfig = aggregatedPowerStatsConfig;
+ }
+
+ AggregatedPowerStatsConfig getConfig() {
return mAggregatedPowerStatsConfig;
}
@@ -71,7 +74,7 @@
* Note: the AggregatedPowerStats object is reused, so the consumer should fully consume
* the stats in the <code>accept</code> method and never cache it.
*/
- public void aggregatePowerStats(long startTimeMs, long endTimeMs,
+ public void aggregatePowerStats(BatteryStatsHistory history, long startTimeMs, long endTimeMs,
Consumer<AggregatedPowerStats> consumer) {
synchronized (this) {
if (mStats == null) {
@@ -85,7 +88,7 @@
long lastTime = 0;
int lastStates = 0xFFFFFFFF;
int lastStates2 = 0xFFFFFFFF;
- try (BatteryStatsHistoryIterator iterator = mHistory.iterate(startTimeMs, endTimeMs)) {
+ try (BatteryStatsHistoryIterator iterator = history.iterate(startTimeMs, endTimeMs)) {
while (iterator.hasNext()) {
BatteryStats.HistoryItem item = iterator.next();
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsExporter.java b/services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java
similarity index 94%
rename from services/core/java/com/android/server/power/stats/PowerStatsExporter.java
rename to services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java
index c5bed24..fab87d6 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsExporter.java
+++ b/services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import android.annotation.Nullable;
import android.os.AggregateBatteryConsumer;
@@ -24,7 +24,11 @@
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BatteryStatsHistory;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.PowerStatsSpan;
+import com.android.server.power.stats.PowerStatsStore;
+import com.android.server.power.stats.format.PowerStatsLayout;
import java.util.ArrayList;
import java.util.Arrays;
@@ -35,19 +39,18 @@
* Given a time range, converts accumulated PowerStats to BatteryUsageStats. Combines
* stores spans of PowerStats with the yet-unprocessed tail of battery history.
*/
-public class PowerStatsExporter {
+class PowerStatsExporter {
private static final String TAG = "PowerStatsExporter";
private final PowerStatsStore mPowerStatsStore;
private final PowerStatsAggregator mPowerStatsAggregator;
private final long mBatterySessionTimeSpanSlackMillis;
private static final long BATTERY_SESSION_TIME_SPAN_SLACK_MILLIS = TimeUnit.MINUTES.toMillis(2);
- public PowerStatsExporter(PowerStatsStore powerStatsStore,
- PowerStatsAggregator powerStatsAggregator) {
+ PowerStatsExporter(PowerStatsStore powerStatsStore, PowerStatsAggregator powerStatsAggregator) {
this(powerStatsStore, powerStatsAggregator, BATTERY_SESSION_TIME_SPAN_SLACK_MILLIS);
}
- public PowerStatsExporter(PowerStatsStore powerStatsStore,
+ PowerStatsExporter(PowerStatsStore powerStatsStore,
PowerStatsAggregator powerStatsAggregator,
long batterySessionTimeSpanSlackMillis) {
mPowerStatsStore = powerStatsStore;
@@ -59,8 +62,8 @@
* Populates the provided BatteryUsageStats.Builder with power estimates from the accumulated
* PowerStats, both stored in PowerStatsStore and not-yet processed.
*/
- public void exportAggregatedPowerStats(BatteryUsageStats.Builder batteryUsageStatsBuilder,
- long monotonicStartTime, long monotonicEndTime) {
+ void exportAggregatedPowerStats(BatteryUsageStats.Builder batteryUsageStatsBuilder,
+ BatteryStatsHistory history, long monotonicStartTime, long monotonicEndTime) {
synchronized (mPowerStatsAggregator) {
boolean hasStoredSpans = false;
long maxEndTime = monotonicStartTime;
@@ -111,7 +114,7 @@
if (!hasStoredSpans
|| maxEndTime < monotonicEndTime - mBatterySessionTimeSpanSlackMillis) {
- mPowerStatsAggregator.aggregatePowerStats(maxEndTime, monotonicEndTime,
+ mPowerStatsAggregator.aggregatePowerStats(history, maxEndTime, monotonicEndTime,
stats -> populateBatteryUsageStatsBuilder(batteryUsageStatsBuilder, stats));
}
mPowerStatsAggregator.reset();
@@ -140,9 +143,7 @@
return;
}
- PowerStatsLayout layout = new PowerStatsLayout();
- layout.fromExtras(descriptor.extras);
-
+ PowerStatsLayout layout = new PowerStatsLayout(descriptor);
long[] deviceStats = new long[descriptor.statsArrayLength];
for (int screenState = 0; screenState < BatteryConsumer.SCREEN_STATE_COUNT; screenState++) {
if (batteryUsageStatsBuilder.isScreenStateDataNeeded()) {
@@ -328,8 +329,8 @@
BatteryConsumer.Key key = getKeyForPartialTotal(batteryUsageStatsBuilder, allAppsScope,
powerComponentId, screenState, powerState);
if (key != null) {
- allAppsScope.addConsumedPower(key, powerAllApps,
- BatteryConsumer.POWER_MODEL_UNDEFINED);
+ allAppsScope.addConsumedPower(key, powerAllApps,
+ BatteryConsumer.POWER_MODEL_UNDEFINED);
}
allAppsScope.addConsumedPower(powerComponentId, powerAllApps,
BatteryConsumer.POWER_MODEL_UNDEFINED);
@@ -393,7 +394,7 @@
return true;
}
- void setPowerComponentEnabled(int powerComponentId, boolean enabled) {
+ public void setPowerComponentEnabled(int powerComponentId, boolean enabled) {
mPowerStatsAggregator.setPowerComponentEnabled(powerComponentId, enabled);
}
}
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/PowerStatsProcessor.java
similarity index 97%
rename from services/core/java/com/android/server/power/stats/PowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/PowerStatsProcessor.java
index 6a8c6b12..838fc62 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/PowerStatsProcessor.java
@@ -13,10 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
-import static com.android.server.power.stats.MultiStateStats.STATE_DOES_NOT_EXIST;
-import static com.android.server.power.stats.MultiStateStats.States.findTrackedStateByName;
+import static com.android.server.power.stats.processor.MultiStateStats.STATE_DOES_NOT_EXIST;
+import static com.android.server.power.stats.processor.MultiStateStats.States.findTrackedStateByName;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -43,7 +43,7 @@
* 2. For each UID, compute the proportion of the combined estimates in each state
* and attribute the corresponding portion of the total power estimate in that state to the UID.
*/
-public abstract class PowerStatsProcessor {
+abstract class PowerStatsProcessor {
private static final String TAG = "PowerStatsProcessor";
private static final double MILLIAMPHOUR_PER_MICROCOULOMB = 1.0 / 1000.0 / 60.0 / 60.0;
diff --git a/services/core/java/com/android/server/power/stats/ScreenPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java
similarity index 93%
rename from services/core/java/com/android/server/power/stats/ScreenPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java
index 8fb1fd6..b295e30 100644
--- a/services/core/java/com/android/server/power/stats/ScreenPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java
@@ -14,28 +14,30 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import static android.os.BatteryConsumer.PROCESS_STATE_UNSPECIFIED;
import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_AMBIENT;
import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_SCREEN_FULL;
import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_SCREEN_ON;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
-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.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
import android.os.BatteryStats;
import android.util.Slog;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.UsageBasedPowerEstimator;
+import com.android.server.power.stats.format.ScreenPowerStatsLayout;
import java.util.ArrayList;
import java.util.List;
-public class ScreenPowerStatsProcessor extends PowerStatsProcessor {
+class ScreenPowerStatsProcessor extends PowerStatsProcessor {
private static final String TAG = "ScreenPowerStatsProcessor";
private final int mDisplayCount;
private final UsageBasedPowerEstimator[] mScreenOnPowerEstimators;
@@ -51,7 +53,7 @@
public double power;
}
- public ScreenPowerStatsProcessor(PowerProfile powerProfile) {
+ ScreenPowerStatsProcessor(PowerProfile powerProfile) {
mDisplayCount = powerProfile.getNumDisplays();
mScreenOnPowerEstimators = new UsageBasedPowerEstimator[mDisplayCount];
mScreenDozePowerEstimators = new UsageBasedPowerEstimator[mDisplayCount];
diff --git a/services/core/java/com/android/server/power/stats/SensorPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/SensorPowerStatsProcessor.java
similarity index 90%
rename from services/core/java/com/android/server/power/stats/SensorPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/SensorPowerStatsProcessor.java
index 79d8076..67013ea 100644
--- a/services/core/java/com/android/server/power/stats/SensorPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/SensorPowerStatsProcessor.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import android.hardware.Sensor;
import android.hardware.SensorManager;
@@ -25,14 +25,16 @@
import android.util.SparseArray;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.PowerStatsLayout;
+import com.android.server.power.stats.format.SensorPowerStatsLayout;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Comparator;
import java.util.List;
import java.util.function.Supplier;
+import java.util.stream.Collectors;
-public class SensorPowerStatsProcessor extends PowerStatsProcessor {
+class SensorPowerStatsProcessor extends PowerStatsProcessor {
private static final String TAG = "SensorPowerStatsProcessor";
private static final String ANDROID_SENSOR_TYPE_PREFIX = "android.sensor.";
@@ -64,7 +66,7 @@
private long[] mTmpDeviceStatsArray;
private long[] mTmpUidStatsArray;
- public SensorPowerStatsProcessor(Supplier<SensorManager> sensorManagerSupplier) {
+ SensorPowerStatsProcessor(Supplier<SensorManager> sensorManagerSupplier) {
mSensorManagerSupplier = sensorManagerSupplier;
}
@@ -78,16 +80,9 @@
return false;
}
- mStatsLayout = new SensorPowerStatsLayout();
- List<Sensor> sensorList = new ArrayList<>(mSensorManager.getSensorList(Sensor.TYPE_ALL));
- sensorList.sort(Comparator.comparingInt(Sensor::getId));
- for (int i = 0; i < sensorList.size(); i++) {
- Sensor sensor = sensorList.get(i);
- String label = makeLabel(sensor, sensorList);
- mStatsLayout.addUidSensorSection(sensor.getHandle(), label);
- }
- mStatsLayout.addUidSectionPowerEstimate();
- mStatsLayout.addDeviceSectionPowerEstimate();
+ List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
+ mStatsLayout = new SensorPowerStatsLayout(sensorList.stream().collect(
+ Collectors.toMap(Sensor::getHandle, sensor -> makeLabel(sensor, sensorList))));
PersistableBundle extras = new PersistableBundle();
mStatsLayout.toExtras(extras);
@@ -231,7 +226,8 @@
sensorState.startTime = time;
}
- private void flushPowerStats(PowerComponentAggregatedPowerStats stats, long timestamp) {
+ private void flushPowerStats(
+ PowerComponentAggregatedPowerStats stats, long timestamp) {
mPowerStats.durationMs = timestamp - mLastUpdateTimestamp;
stats.addProcessedPowerStats(mPowerStats, timestamp);
@@ -240,7 +236,8 @@
mLastUpdateTimestamp = timestamp;
}
- private void computeUidPowerEstimates(PowerComponentAggregatedPowerStats stats,
+ private void computeUidPowerEstimates(
+ PowerComponentAggregatedPowerStats stats,
List<Integer> uids) {
List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
int[] uidSensorDurationPositions = new int[sensorList.size()];
@@ -292,7 +289,8 @@
}
}
- private void computeDevicePowerEstimates(PowerComponentAggregatedPowerStats stats) {
+ private void computeDevicePowerEstimates(
+ PowerComponentAggregatedPowerStats stats) {
for (int i = mPlan.combinedDeviceStateEstimations.size() - 1; i >= 0; i--) {
CombinedDeviceStateEstimate estimation =
mPlan.combinedDeviceStateEstimations.get(i);
diff --git a/services/core/java/com/android/server/power/stats/VideoPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/VideoPowerStatsProcessor.java
similarity index 80%
rename from services/core/java/com/android/server/power/stats/VideoPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/VideoPowerStatsProcessor.java
index 48dac8a..a6c3807 100644
--- a/services/core/java/com/android/server/power/stats/VideoPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/VideoPowerStatsProcessor.java
@@ -14,16 +14,16 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import com.android.internal.os.PowerProfile;
+import com.android.server.power.stats.PowerStatsUidResolver;
-public class VideoPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
- public VideoPowerStatsProcessor(PowerProfile powerProfile,
- PowerStatsUidResolver uidResolver) {
+class VideoPowerStatsProcessor extends BinaryStatePowerStatsProcessor {
+ VideoPowerStatsProcessor(PowerProfile powerProfile, PowerStatsUidResolver uidResolver) {
super(BatteryConsumer.POWER_COMPONENT_VIDEO, uidResolver,
powerProfile.getAveragePower(PowerProfile.POWER_VIDEO));
}
diff --git a/services/core/java/com/android/server/power/stats/WifiPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/WifiPowerStatsProcessor.java
similarity index 98%
rename from services/core/java/com/android/server/power/stats/WifiPowerStatsProcessor.java
rename to services/core/java/com/android/server/power/stats/processor/WifiPowerStatsProcessor.java
index 4e035c3..0df01cf 100644
--- a/services/core/java/com/android/server/power/stats/WifiPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/WifiPowerStatsProcessor.java
@@ -14,18 +14,20 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import android.util.Slog;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.UsageBasedPowerEstimator;
+import com.android.server.power.stats.format.WifiPowerStatsLayout;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-public class WifiPowerStatsProcessor extends PowerStatsProcessor {
+class WifiPowerStatsProcessor extends PowerStatsProcessor {
private static final String TAG = "WifiPowerStatsProcessor";
private static final boolean DEBUG = false;
@@ -46,7 +48,7 @@
private long[] mTmpUidStatsArray;
private boolean mHasWifiPowerController;
- public WifiPowerStatsProcessor(PowerProfile powerProfile) {
+ WifiPowerStatsProcessor(PowerProfile powerProfile) {
mRxPowerEstimator = new UsageBasedPowerEstimator(
powerProfile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_RX));
mTxPowerEstimator = new UsageBasedPowerEstimator(
diff --git a/services/core/java/com/android/server/rollback/ApexdRevertLogger.java b/services/core/java/com/android/server/rollback/ApexdRevertLogger.java
new file mode 100644
index 0000000..9950cc7
--- /dev/null
+++ b/services/core/java/com/android/server/rollback/ApexdRevertLogger.java
@@ -0,0 +1,167 @@
+/*
+ * 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.rollback;
+
+import static com.android.server.crashrecovery.proto.CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED;
+import static com.android.server.crashrecovery.proto.CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH_DURING_BOOT;
+import static com.android.server.crashrecovery.proto.CrashRecoveryStatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.VersionedPackage;
+import android.os.SystemProperties;
+import android.util.ArraySet;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.crashrecovery.proto.CrashRecoveryStatsLog;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This class handles the logic for logging Apexd-triggered rollback events.
+ * TODO: b/354112511 Refactor to have a separate metric for ApexdReverts
+ */
+public final class ApexdRevertLogger {
+ private static final String TAG = "WatchdogRollbackLogger";
+
+ private static final String LOGGING_PARENT_KEY = "android.content.pm.LOGGING_PARENT";
+
+ /**
+ * Logs that one or more apexd reverts have occurred, along with the crashing native process
+ * that caused apexd to revert during boot.
+ *
+ * @param context the context to use when determining the log packages
+ * @param failedPackageNames a list of names of packages which were reverted
+ * @param failingNativeProcess the crashing native process which caused a revert
+ */
+ public static void logApexdRevert(Context context, @NonNull List<String> failedPackageNames,
+ @NonNull String failingNativeProcess) {
+ Set<VersionedPackage> logPackages = getLogPackages(context, failedPackageNames);
+ for (VersionedPackage logPackage: logPackages) {
+ logEvent(logPackage,
+ failingNativeProcess);
+ }
+ }
+
+ /**
+ * Gets the set of parent packages for a given set of failed package names. In the case that
+ * multiple sessions have failed, we want to log failure for each of the parent packages.
+ * Even if multiple failed packages have the same parent, we only log the parent package once.
+ */
+ private static Set<VersionedPackage> getLogPackages(Context context,
+ @NonNull List<String> failedPackageNames) {
+ Set<VersionedPackage> parentPackages = new ArraySet<>();
+ for (String failedPackageName: failedPackageNames) {
+ parentPackages.add(getLogPackage(context, new VersionedPackage(failedPackageName, 0)));
+ }
+ return parentPackages;
+ }
+
+ /**
+ * Returns the logging parent of a given package if it exists, {@code null} otherwise.
+ *
+ * The logging parent is defined by the {@code android.content.pm.LOGGING_PARENT} field in the
+ * metadata of a package's AndroidManifest.xml.
+ */
+ @VisibleForTesting
+ @Nullable
+ private static VersionedPackage getLogPackage(Context context,
+ @NonNull VersionedPackage failingPackage) {
+ String logPackageName;
+ VersionedPackage loggingParent;
+ logPackageName = getLoggingParentName(context, failingPackage.getPackageName());
+ if (logPackageName == null) {
+ return null;
+ }
+ try {
+ loggingParent = new VersionedPackage(logPackageName, context.getPackageManager()
+ .getPackageInfo(logPackageName, 0 /* flags */).getLongVersionCode());
+ } catch (PackageManager.NameNotFoundException e) {
+ return null;
+ }
+ return loggingParent;
+ }
+
+ @Nullable
+ private static String getLoggingParentName(Context context, @NonNull String packageName) {
+ PackageManager packageManager = context.getPackageManager();
+ try {
+ int flags = PackageManager.MATCH_APEX | PackageManager.GET_META_DATA;
+ ApplicationInfo ai = packageManager.getPackageInfo(packageName, flags).applicationInfo;
+ if (ai == null || ai.metaData == null) {
+ return null;
+ }
+ return ai.metaData.getString(LOGGING_PARENT_KEY);
+ } catch (Exception e) {
+ Slog.w(TAG, "Unable to discover logging parent package: " + packageName, e);
+ return null;
+ }
+ }
+
+ /**
+ * Log a Apexd rollback event to statsd.
+ *
+ * @param logPackage the package to associate the rollback with.
+ * @param failingPackageName the failing package or process which triggered the rollback.
+ */
+ private static void logEvent(@Nullable VersionedPackage logPackage,
+ @NonNull String failingPackageName) {
+ Slog.i(TAG, "Watchdog event occurred with type: ROLLBACK_SUCCESS"
+ + " logPackage: " + logPackage
+ + " rollbackReason: REASON_NATIVE_CRASH_DURING_BOOT"
+ + " failedPackageName: " + failingPackageName);
+ CrashRecoveryStatsLog.write(
+ WATCHDOG_ROLLBACK_OCCURRED,
+ WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
+ (logPackage != null) ? logPackage.getPackageName() : "",
+ (logPackage != null) ? logPackage.getVersionCode() : 0,
+ WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH_DURING_BOOT,
+ failingPackageName,
+ new byte[]{});
+
+ logTestProperties(logPackage, failingPackageName);
+ }
+
+ /**
+ * Writes properties which will be used by rollback tests to check if rollback has occurred
+ * have occurred.
+ *
+ * persist.sys.rollbacktest.enabled: true if rollback tests are running
+ * persist.sys.rollbacktest.ROLLBACK_SUCCESS.logPackage: the package to associate the rollback
+ * persist.sys.rollbacktest.ROLLBACK_SUCCESS.rollbackReason: the reason Apexd triggered it
+ * persist.sys.rollbacktest.ROLLBACK_SUCCESS.failedPackageName: the failing package or process
+ * which triggered the rollback
+ */
+ private static void logTestProperties(@Nullable VersionedPackage logPackage,
+ @NonNull String failingPackageName) {
+ // This property should be on only during the tests
+ final String prefix = "persist.sys.rollbacktest.";
+ if (!SystemProperties.getBoolean(prefix + "enabled", false)) {
+ return;
+ }
+ String key = prefix + "ROLLBACK_SUCCESS";
+ SystemProperties.set(key, String.valueOf(true));
+ SystemProperties.set(key + ".logPackage", logPackage != null ? logPackage.toString() : "");
+ SystemProperties.set(key + ".rollbackReason", "REASON_NATIVE_CRASH_DURING_BOOT");
+ SystemProperties.set(key + ".failedPackageName", failingPackageName);
+ }
+}
diff --git a/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java b/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java
index 7fc0292..d763199 100644
--- a/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java
+++ b/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java
@@ -165,25 +165,6 @@
}
/**
- * Logs that one or more apexd reverts have occurred, along with the crashing native process
- * that caused apexd to revert during boot.
- *
- * @param context the context to use when determining the log packages
- * @param failedPackageNames a list of names of packages which were reverted
- * @param failingNativeProcess the crashing native process which caused a revert
- */
- public static void logApexdRevert(Context context, @NonNull List<String> failedPackageNames,
- @NonNull String failingNativeProcess) {
- Set<VersionedPackage> logPackages = getLogPackages(context, failedPackageNames);
- for (VersionedPackage logPackage: logPackages) {
- logEvent(logPackage,
- WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
- WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH_DURING_BOOT,
- failingNativeProcess);
- }
- }
-
- /**
* Log a Watchdog rollback event to statsd.
*
* @param logPackage the package to associate the rollback with.
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 67900f8..91a17a9 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -599,13 +599,6 @@
ComponentName component = it.next();
ServiceState serviceState = userState.serviceStateMap.get(component);
if (serviceState != null && serviceState.sessionTokens.isEmpty()) {
- if (serviceState.callback != null) {
- try {
- serviceState.service.unregisterCallback(serviceState.callback);
- } catch (RemoteException e) {
- Slog.e(TAG, "error in unregisterCallback", e);
- }
- }
unbindService(serviceState);
it.remove();
}
@@ -667,13 +660,6 @@
// Unregister all callbacks and unbind all services.
for (ServiceState serviceState : userState.serviceStateMap.values()) {
if (serviceState.service != null) {
- if (serviceState.callback != null) {
- try {
- serviceState.service.unregisterCallback(serviceState.callback);
- } catch (RemoteException e) {
- Slog.e(TAG, "error in unregisterCallback", e);
- }
- }
unbindService(serviceState);
}
}
@@ -3306,7 +3292,20 @@
return filteredDisplayName;
}
- private static final class UserState {
+ private class TvInputManagerCallbackList extends RemoteCallbackList<ITvInputManagerCallback> {
+ @Override
+ public void onCallbackDied(ITvInputManagerCallback callback) {
+ synchronized (mLock) {
+ for (int i = 0; i < mUserStates.size(); i++) {
+ int userId = mUserStates.keyAt(i);
+ UserState userState = getOrCreateUserStateLocked(userId);
+ userState.callbackPidUidMap.remove(callback);
+ }
+ }
+ }
+ }
+
+ private final class UserState {
// A mapping from the TV input id to its TvInputState.
private Map<String, TvInputState> inputMap = new HashMap<>();
@@ -3327,8 +3326,8 @@
private final Map<IBinder, SessionState> sessionStateMap = new HashMap<>();
// A list of callbacks.
- private final RemoteCallbackList<ITvInputManagerCallback> mCallbacks =
- new RemoteCallbackList<>();
+ private final TvInputManagerCallbackList mCallbacks =
+ new TvInputManagerCallbackList();
private final Map<ITvInputManagerCallback, Pair<Integer, Integer>> callbackPidUidMap =
new HashMap<>();
@@ -3558,12 +3557,19 @@
@GuardedBy("mLock")
private void unbindService(ServiceState serviceState) {
- if (!serviceState.bound) {
+ if (serviceState == null || !serviceState.bound) {
return;
}
if (DEBUG) {
Slog.d(TAG, "unbindService(service=" + serviceState.component + ")");
}
+ if (serviceState.callback != null) {
+ try {
+ serviceState.service.unregisterCallback(serviceState.callback);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in unregisterCallback", e);
+ }
+ }
mContext.unbindService(serviceState.connection);
serviceState.bound = false;
serviceState.service = null;
@@ -3781,9 +3787,9 @@
if (serviceState.hardwareInputMap.containsKey(inputInfo.getId())) {
return;
}
- Slog.d("ServiceCallback",
- "addHardwareInput: device id " + deviceId + ", "
- + inputInfo.toString());
+ Slog.d(TAG, "ServiceCallback: addHardwareInput, deviceId: " + deviceId +
+ ", inputInfo: " + inputInfo.toString() + " by " + mComponent +
+ ", userId: " + mUserId);
mTvInputHardwareManager.addHardwareInput(deviceId, inputInfo);
addHardwareInputLocked(inputInfo, mComponent, mUserId);
}
@@ -3802,6 +3808,9 @@
if (serviceState.hardwareInputMap.containsKey(inputInfo.getId())) {
return;
}
+ Slog.d(TAG, "ServiceCallback: addHdmiInput, id: " + id +
+ ", inputInfo: "+ inputInfo.toString() + " by " + mComponent +
+ ", userId: " + mUserId);
mTvInputHardwareManager.addHdmiInput(id, inputInfo);
addHardwareInputLocked(inputInfo, mComponent, mUserId);
if (mOnScreenInputId != null && mOnScreenSessionState != null) {
@@ -3832,8 +3841,8 @@
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- Slog.d("ServiceCallback",
- "removeHardwareInput " + inputId + " by " + mComponent);
+ Slog.d(TAG, "ServiceCallback: removeHardwareInput, inputId: " + inputId +
+ " by " + mComponent + ", userId: " + mUserId);
removeHardwareInputLocked(inputId, mUserId);
}
} finally {
diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
index ecd140e..96a25da 100644
--- a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
+++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
@@ -44,7 +44,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
-import com.android.internal.telephony.flags.Flags;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
@@ -324,11 +323,8 @@
if (SubscriptionManager.isValidSubscriptionId(subId)) {
// Get only configs as needed to save memory.
final PersistableBundle carrierConfig =
- Flags.fixCrashOnGettingConfigWhenPhoneIsGone()
- ? CarrierConfigManager.getCarrierConfigSubset(mContext, subId,
- VcnManager.VCN_RELATED_CARRIER_CONFIG_KEYS)
- : mCarrierConfigManager.getConfigForSubId(subId,
- VcnManager.VCN_RELATED_CARRIER_CONFIG_KEYS);
+ CarrierConfigManager.getCarrierConfigSubset(mContext, subId,
+ VcnManager.VCN_RELATED_CARRIER_CONFIG_KEYS);
if (mDeps.isConfigForIdentifiedCarrier(carrierConfig)) {
mReadySubIdsBySlotId.put(slotId, subId);
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index f53dda6..4dcc6e1 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -3169,7 +3169,8 @@
final WallpaperDestinationChangeHandler
liveSync = new WallpaperDestinationChangeHandler(
newWallpaper);
- boolean same = changingToSame(name, newWallpaper);
+ boolean same = changingToSame(name, newWallpaper.connection,
+ newWallpaper.wallpaperComponent);
/*
* If we have a shared system+lock wallpaper, and we reapply the same wallpaper
@@ -3257,14 +3258,15 @@
return name == null || name.equals(mDefaultWallpaperComponent);
}
- private boolean changingToSame(ComponentName componentName, WallpaperData wallpaper) {
- if (wallpaper.connection != null) {
- final ComponentName wallpaperName = wallpaper.wallpaperComponent;
- if (isDefaultComponent(componentName) && isDefaultComponent(wallpaperName)) {
+ private boolean changingToSame(ComponentName newComponentName,
+ WallpaperConnection currentConnection, ComponentName currentComponentName) {
+ if (currentConnection != null) {
+ if (isDefaultComponent(newComponentName) && isDefaultComponent(currentComponentName)) {
if (DEBUG) Slog.v(TAG, "changingToSame: still using default");
// Still using default wallpaper.
return true;
- } else if (wallpaperName != null && wallpaperName.equals(componentName)) {
+ } else if (currentComponentName != null && currentComponentName.equals(
+ newComponentName)) {
// Changing to same wallpaper.
if (DEBUG) Slog.v(TAG, "same wallpaper");
return true;
@@ -3279,7 +3281,8 @@
Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
}
// Has the component changed?
- if (!force && changingToSame(componentName, wallpaper)) {
+ if (!force && changingToSame(componentName, wallpaper.connection,
+ wallpaper.wallpaperComponent)) {
try {
if (DEBUG_LIVE) {
Slog.v(TAG, "Changing to the same component, ignoring");
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index c1e859d..e27b2be 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -864,9 +864,8 @@
if (transition != null) {
if (changed) {
// Always set as scene transition because it expects to be a jump-cut.
- transition.setOverrideAnimation(
- TransitionInfo.AnimationOptions.makeSceneTransitionAnimOptions(), r,
- null, null);
+ transition.setOverrideAnimation(TransitionInfo.AnimationOptions
+ .makeSceneTransitionAnimOptions(), null, null);
r.mTransitionController.requestStartTransition(transition,
null /*startTask */, null /* remoteTransition */,
null /* displayChange */);
@@ -911,9 +910,8 @@
&& under.returningOptions.getAnimationType()
== ANIM_SCENE_TRANSITION) {
// Pass along the scene-transition animation-type
- transition.setOverrideAnimation(TransitionInfo
- .AnimationOptions.makeSceneTransitionAnimOptions(), r,
- null, null);
+ transition.setOverrideAnimation(TransitionInfo.AnimationOptions
+ .makeSceneTransitionAnimOptions(), null, null);
}
} else {
transition.abort();
@@ -1510,7 +1508,7 @@
r.mOverrideTaskTransition);
r.mTransitionController.setOverrideAnimation(
TransitionInfo.AnimationOptions.makeCustomAnimOptions(packageName,
- enterAnim, exitAnim, backgroundColor, r.mOverrideTaskTransition), r,
+ enterAnim, exitAnim, backgroundColor, r.mOverrideTaskTransition),
null /* startCallback */, null /* finishCallback */);
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index e562ea8..0be6471 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -353,7 +353,6 @@
import android.window.SplashScreenView;
import android.window.SplashScreenView.SplashScreenViewParcelable;
import android.window.TaskSnapshot;
-import android.window.TransitionInfo;
import android.window.TransitionInfo.AnimationOptions;
import android.window.WindowContainerToken;
import android.window.WindowOnBackInvokedDispatcher;
@@ -5049,8 +5048,7 @@
// controller but don't clear the animation information from the options since they
// need to be sent to the animating activity.
mTransitionController.setOverrideAnimation(
- TransitionInfo.AnimationOptions.makeSceneTransitionAnimOptions(), this,
- null, null);
+ AnimationOptions.makeSceneTransitionAnimOptions(), null, null);
return;
}
applyOptionsAnimation(mPendingOptions, intent);
@@ -5173,8 +5171,7 @@
}
if (options != null) {
- mTransitionController.setOverrideAnimation(options, this, startCallback,
- finishCallback);
+ mTransitionController.setOverrideAnimation(options, startCallback, finishCallback);
}
}
@@ -8152,7 +8149,8 @@
*/
@Override
protected int getOverrideOrientation() {
- if (mWmService.mConstants.mIgnoreActivityOrientationRequest) {
+ if (mWmService.mConstants.mIgnoreActivityOrientationRequest
+ && info.applicationInfo.category != ApplicationInfo.CATEGORY_GAME) {
return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
}
return mAppCompatController.getOrientationPolicy()
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index 1660ca9..35ec5ad 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -424,13 +424,19 @@
Intent intent = intents[i];
NeededUriGrants intentGrants = null;
- intent.prepareToEnterSystemServer();
+ // Refuse possible leaked file descriptors.
+ if (intent.hasFileDescriptors()) {
+ throw new IllegalArgumentException("File descriptors passed in Intent");
+ }
// Get the flag earlier because the intent may be modified in resolveActivity below.
final boolean componentSpecified = intent.getComponent() != null;
// Don't modify the client's object!
intent = new Intent(intent);
+ // Remove existing mismatch flag so it can be properly updated later
+ intent.removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);
+
// Collect information about the target of the Intent.
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i],
0 /* startFlags */, null /* profilerInfo */, userId, filterCallingUid,
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index bf18a43..1822a80 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -721,7 +721,13 @@
onExecutionStarted();
if (mRequest.intent != null) {
- mRequest.intent.prepareToEnterSystemServer();
+ // Refuse possible leaked file descriptors
+ if (mRequest.intent.hasFileDescriptors()) {
+ throw new IllegalArgumentException("File descriptors passed in Intent");
+ }
+
+ // Remove existing mismatch flag so it can be properly updated later
+ mRequest.intent.removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);
}
final LaunchingState launchingState;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 26a6b00..3d6b64b 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -130,35 +130,6 @@
}
/**
- * Sleep tokens cause the activity manager to put the top activity to sleep.
- * They are used by components such as dreams that may hide and block interaction
- * with underlying activities.
- * The Acquirer provides an interface that encapsulates the underlying work, so the user does
- * not need to handle the token by him/herself.
- */
- public interface SleepTokenAcquirer {
-
- /**
- * Acquires a sleep token.
- * @param displayId The display to apply to.
- */
- void acquire(int displayId);
-
- /**
- * Releases the sleep token.
- * @param displayId The display to apply to.
- */
- void release(int displayId);
- }
-
- /**
- * Creates a sleep token acquirer for the specified display with the specified tag.
- *
- * @param tag A string identifying the purpose (eg. "Dream").
- */
- public abstract SleepTokenAcquirer createSleepTokenAcquirer(@NonNull String tag);
-
- /**
* Returns home activity for the specified user.
*
* @param userId ID of the user or {@link android.os.UserHandle#USER_ALL}
@@ -380,7 +351,16 @@
public abstract void onPackageAdded(String name, boolean replacing);
public abstract void onPackageReplaced(ApplicationInfo aInfo);
- public abstract CompatibilityInfo compatibilityInfoForPackage(ApplicationInfo ai);
+ /** The data for IApplicationThread#bindApplication. */
+ public static final class PreBindInfo {
+ public final @NonNull CompatibilityInfo compatibilityInfo;
+ public final @NonNull Configuration configuration;
+
+ PreBindInfo(@NonNull CompatibilityInfo compatInfo, @NonNull Configuration config) {
+ compatibilityInfo = compatInfo;
+ configuration = config;
+ }
+ }
public final class ActivityTokens {
private final @NonNull IBinder mActivityToken;
@@ -502,7 +482,9 @@
public abstract void resumeTopActivities(boolean scheduleIdle);
/** Called by AM just before it binds to an application process. */
- public abstract void preBindApplication(WindowProcessController wpc);
+ @NonNull
+ public abstract PreBindInfo preBindApplication(@NonNull WindowProcessController wpc,
+ @NonNull ApplicationInfo info);
/** Called by AM when an application process attaches. */
public abstract boolean attachApplication(WindowProcessController wpc) throws RemoteException;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index f5476f2..49ca698 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1317,7 +1317,12 @@
String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle bOptions) {
enforceNotIsolatedCaller("startActivityIntentSender");
if (fillInIntent != null) {
- fillInIntent.prepareToEnterSystemServer();
+ // Refuse possible leaked file descriptors
+ if (fillInIntent.hasFileDescriptors()) {
+ throw new IllegalArgumentException("File descriptors passed in Intent");
+ }
+ // Remove existing mismatch flag so it can be properly updated later
+ fillInIntent.removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);
}
if (!(target instanceof PendingIntentRecord)) {
@@ -1343,10 +1348,10 @@
@Override
public boolean startNextMatchingActivity(IBinder callingActivity, Intent intent,
Bundle bOptions) {
- if (intent != null) {
- intent.prepareToEnterSystemServer();
+ // Refuse possible leaked file descriptors
+ if (intent != null && intent.hasFileDescriptors()) {
+ throw new IllegalArgumentException("File descriptors passed in Intent");
}
-
SafeActivityOptions options = SafeActivityOptions.fromBundle(bOptions);
synchronized (mGlobalLock) {
@@ -1361,6 +1366,8 @@
return false;
}
intent = new Intent(intent);
+ // Remove existing mismatch flag so it can be properly updated later
+ intent.removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);
// The caller is not allowed to change the data.
intent.setDataAndType(r.intent.getData(), r.intent.getType());
// And we are resetting to find the next component...
@@ -4349,6 +4356,7 @@
mTaskOrganizerController.dump(pw, " ");
mVisibleActivityProcessTracker.dump(pw, " ");
mActiveUids.dump(pw, " ");
+ pw.println(" SleepTokens=" + mRootWindowContainer.mSleepTokens);
if (mDemoteTopAppReasons != 0) {
pw.println(" mDemoteTopAppReasons=" + mDemoteTopAppReasons);
}
@@ -5064,17 +5072,16 @@
EventLogTags.writeWmSetResumedActivity(r.mUserId, r.shortComponentName, reason);
}
- final class SleepTokenAcquirerImpl implements ActivityTaskManagerInternal.SleepTokenAcquirer {
+ final class SleepTokenAcquirer {
private final String mTag;
private final SparseArray<RootWindowContainer.SleepToken> mSleepTokens =
new SparseArray<>();
- SleepTokenAcquirerImpl(@NonNull String tag) {
+ SleepTokenAcquirer(@NonNull String tag) {
mTag = tag;
}
- @Override
- public void acquire(int displayId) {
+ void acquire(int displayId) {
synchronized (mGlobalLock) {
if (!mSleepTokens.contains(displayId)) {
mSleepTokens.append(displayId,
@@ -5084,8 +5091,7 @@
}
}
- @Override
- public void release(int displayId) {
+ void release(int displayId) {
synchronized (mGlobalLock) {
final RootWindowContainer.SleepToken token = mSleepTokens.get(displayId);
if (token != null) {
@@ -5948,11 +5954,6 @@
}
final class LocalService extends ActivityTaskManagerInternal {
- @Override
- public SleepTokenAcquirer createSleepTokenAcquirer(@NonNull String tag) {
- Objects.requireNonNull(tag);
- return new SleepTokenAcquirerImpl(tag);
- }
@Override
public ComponentName getHomeActivityForUser(int userId) {
@@ -6421,13 +6422,6 @@
}
@Override
- public CompatibilityInfo compatibilityInfoForPackage(ApplicationInfo ai) {
- synchronized (mGlobalLock) {
- return compatibilityInfoForPackageLocked(ai);
- }
- }
-
- @Override
public void sendActivityResult(int callingUid, IBinder activityToken, String resultWho,
int requestCode, int resultCode, Intent data) {
final ActivityRecord r;
@@ -6705,9 +6699,13 @@
@HotPath(caller = HotPath.PROCESS_CHANGE)
@Override
- public void preBindApplication(WindowProcessController wpc) {
+ public PreBindInfo preBindApplication(WindowProcessController wpc, ApplicationInfo info) {
synchronized (mGlobalLockWithoutBoost) {
mTaskSupervisor.getActivityMetricsLogger().notifyBindApplication(wpc.mInfo);
+ wpc.onConfigurationChanged(getGlobalConfiguration());
+ // The "info" can be the target of instrumentation.
+ return new PreBindInfo(compatibilityInfoForPackageLocked(info),
+ new Configuration(wpc.getConfiguration()));
}
}
@@ -7474,9 +7472,7 @@
FEATURE_LEANBACK);
final boolean isArc = arcFeature != null && arcFeature.version >= 0;
final boolean isTv = tvFeature != null && tvFeature.version >= 0;
- sIsPip2ExperimentEnabled = SystemProperties.getBoolean(
- "persist.wm_shell.pip2", false)
- || (Flags.enablePip2Implementation() && !isArc && !isTv);
+ sIsPip2ExperimentEnabled = Flags.enablePip2() && !isArc && !isTv;
}
return sIsPip2ExperimentEnabled;
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index e90a2c9..9a3ad2d 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -107,7 +107,6 @@
import android.app.servertransaction.PauseActivityItem;
import android.app.servertransaction.ResumeActivityItem;
import android.app.servertransaction.StopActivityItem;
-import android.companion.virtual.VirtualDeviceManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -158,6 +157,7 @@
import com.android.server.am.ActivityManagerService;
import com.android.server.am.HostingRecord;
import com.android.server.am.UserState;
+import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
import com.android.server.pm.SaferIntentUtils;
import com.android.server.utils.Slogf;
import com.android.server.wm.ActivityMetricsLogger.LaunchingState;
@@ -285,7 +285,7 @@
private WindowManagerService mWindowManager;
private AppOpsManager mAppOpsManager;
- private VirtualDeviceManager mVirtualDeviceManager;
+ private VirtualDeviceManagerInternal mVirtualDeviceManagerInternal;
/** Common synchronization logic used to save things to disks. */
PersisterQueue mPersisterQueue;
@@ -1298,16 +1298,24 @@
if (displayId == DEFAULT_DISPLAY || displayId == INVALID_DISPLAY) {
return Context.DEVICE_ID_DEFAULT;
}
- if (mVirtualDeviceManager == null) {
+ if (mVirtualDeviceManagerInternal == null) {
if (mService.mHasCompanionDeviceSetupFeature) {
- mVirtualDeviceManager =
- mService.mContext.getSystemService(VirtualDeviceManager.class);
+ mVirtualDeviceManagerInternal =
+ LocalServices.getService(VirtualDeviceManagerInternal.class);
}
- if (mVirtualDeviceManager == null) {
+ if (mVirtualDeviceManagerInternal == null) {
return Context.DEVICE_ID_DEFAULT;
}
}
- return mVirtualDeviceManager.getDeviceIdForDisplayId(displayId);
+ return mVirtualDeviceManagerInternal.getDeviceIdForDisplayId(displayId);
+ }
+
+ boolean isDeviceOwnerUid(int displayId, int callingUid) {
+ final int deviceId = getDeviceIdForDisplayId(displayId);
+ if (deviceId == Context.DEVICE_ID_DEFAULT || deviceId == Context.DEVICE_ID_INVALID) {
+ return false;
+ }
+ return mVirtualDeviceManagerInternal.getDeviceOwnerUid(deviceId) == callingUid;
}
private AppOpsManager getAppOpsManager() {
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 28dbc3a..4e4616d 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -339,13 +339,12 @@
removedWindowContainer,
BackNavigationInfo.typeToString(backType));
- // For now, we only animate when going home, cross task or cross-activity.
boolean prepareAnimation =
(backType == BackNavigationInfo.TYPE_RETURN_TO_HOME
|| backType == BackNavigationInfo.TYPE_CROSS_TASK
|| backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY
|| backType == BackNavigationInfo.TYPE_DIALOG_CLOSE)
- && adapter != null;
+ && (adapter != null && adapter.isAnimatable(backType));
if (prepareAnimation) {
final AnimationHandler.ScheduleAnimationBuilder builder =
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 34bbe6a..10e0641 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -235,7 +235,6 @@
import android.view.Surface.Rotation;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
-import android.view.SurfaceSession;
import android.view.WindowInsets;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowManager;
@@ -572,8 +571,6 @@
boolean mWallpaperMayChange = false;
- private final SurfaceSession mSession = new SurfaceSession();
-
/**
* A perf hint session which will boost the refresh rate for the display and change sf duration
* to handle larger workloads.
@@ -738,8 +735,6 @@
/** All tokens used to put activities on this root task to sleep (including mOffToken) */
final ArrayList<RootWindowContainer.SleepToken> mAllSleepTokens = new ArrayList<>();
- /** The token acquirer to put root tasks on the display to sleep */
- private final ActivityTaskManagerInternal.SleepTokenAcquirer mOffTokenAcquirer;
private boolean mSleeping;
@@ -1134,7 +1129,6 @@
mDisplay = display;
mDisplayId = display.getDisplayId();
mCurrentUniqueDisplayId = display.getUniqueId();
- mOffTokenAcquirer = mRootWindowContainer.mDisplayOffTokenAcquirer;
mWallpaperController = new WallpaperController(mWmService, this);
mWallpaperController.resetLargestDisplay(display);
display.getDisplayInfo(mDisplayInfo);
@@ -1284,7 +1278,7 @@
* @param transaction as part of which to perform the configuration
*/
private void configureSurfaces(Transaction transaction) {
- final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(mSession)
+ final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder()
.setOpaque(true)
.setContainerLayer()
.setCallsite("DisplayContent");
@@ -3215,22 +3209,21 @@
* If xPpi or yDpi is equal to {@link #INVALID_DPI}, the values are ignored.
*/
void setForcedSize(int width, int height, float xDPI, float yDPI) {
- // Can't force size higher than the maximal allowed
- if (mMaxUiWidth > 0 && width > mMaxUiWidth) {
- final float ratio = mMaxUiWidth / (float) width;
- height = (int) (height * ratio);
- width = mMaxUiWidth;
- }
-
mIsSizeForced = mInitialDisplayWidth != width || mInitialDisplayHeight != height;
if (mIsSizeForced) {
+ if (mMaxUiWidth > 0 && width > mMaxUiWidth) {
+ final float ratio = mMaxUiWidth / (float) width;
+ height = (int) (height * ratio);
+ width = mMaxUiWidth;
+ }
final Point size = getValidForcedSize(width, height);
width = size.x;
height = size.y;
}
Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
- updateBaseDisplayMetrics(width, height, mBaseDisplayDensity,
+ updateBaseDisplayMetrics(width, height,
+ mIsDensityForced ? mBaseDisplayDensity : mInitialDisplayDensity,
xDPI != INVALID_DPI ? xDPI : mBaseDisplayPhysicalXDpi,
yDPI != INVALID_DPI ? yDPI : mBaseDisplayPhysicalYDpi);
reconfigureDisplayLocked();
@@ -4597,7 +4590,7 @@
// removed on the task.
removeImeSurfaceImmediately();
mImeScreenshot = new ImeScreenshot(
- mWmService.mSurfaceControlFactory.apply(null), imeTarget);
+ mWmService.mSurfaceControlFactory.get(), imeTarget);
// If the caller requests to hide IME, then allow to show IME snapshot for any target task.
// So IME won't look like suddenly disappeared. It usually happens when turning off screen.
mImeScreenshot.attachAndShow(t, hideImeWindow /* anyTargetTask */);
@@ -5430,14 +5423,8 @@
}
@Override
- SurfaceSession getSession() {
- return mSession;
- }
-
- @Override
SurfaceControl.Builder makeChildSurface(WindowContainer child) {
- SurfaceSession s = child != null ? child.getSession() : getSession();
- final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(s).setContainerLayer();
+ final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder().setContainerLayer();
if (child == null) {
return b;
}
@@ -5453,12 +5440,12 @@
* and other potpourii.
*/
SurfaceControl.Builder makeOverlay() {
- return mWmService.makeSurfaceBuilder(mSession).setParent(getOverlayLayer());
+ return mWmService.makeSurfaceBuilder().setParent(getOverlayLayer());
}
@Override
public SurfaceControl.Builder makeAnimationLeash() {
- return mWmService.makeSurfaceBuilder(mSession).setParent(mSurfaceControl)
+ return mWmService.makeSurfaceBuilder().setParent(mSurfaceControl)
.setContainerLayer();
}
@@ -6167,9 +6154,9 @@
final int displayState = mDisplayInfo.state;
if (displayId != DEFAULT_DISPLAY) {
if (displayState == Display.STATE_OFF) {
- mOffTokenAcquirer.acquire(mDisplayId);
+ mRootWindowContainer.mDisplayOffTokenAcquirer.acquire(mDisplayId);
} else if (displayState == Display.STATE_ON) {
- mOffTokenAcquirer.release(mDisplayId);
+ mRootWindowContainer.mDisplayOffTokenAcquirer.release(mDisplayId);
}
ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
"Content Recording: Display %d state was (%d), is now (%d), so update "
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 745b792..107d31e 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -804,6 +804,14 @@
mAwake /* waiting */);
if (!awake) {
onDisplaySwitchFinished();
+ // In case PhoneWindowManager's startedGoingToSleep is called after screenTurnedOff
+ // (the source caller is in order but the methods run on different threads) and
+ // updateScreenOffSleepToken was skipped by mIsGoingToSleepDefaultDisplay. Then
+ // acquire sleep token if screen is off.
+ if (!mScreenOnEarly && !mScreenOnFully && !mDisplayContent.isSleeping()) {
+ Slog.w(TAG, "Late acquire sleep token for " + mDisplayContent);
+ mService.mRoot.mDisplayOffTokenAcquirer.acquire(mDisplayContent.mDisplayId);
+ }
}
}
}
@@ -851,6 +859,7 @@
public void screenTurningOn(ScreenOnListener screenOnListener) {
WindowProcessController visibleDozeUiProcess = null;
synchronized (mLock) {
+ mService.mRoot.mDisplayOffTokenAcquirer.release(mDisplayContent.mDisplayId);
mScreenOnEarly = true;
mScreenOnFully = false;
mKeyguardDrawComplete = false;
@@ -875,8 +884,12 @@
onDisplaySwitchFinished();
}
- public void screenTurnedOff() {
+ /** It is called after {@link #screenTurningOn}. This runs on PowerManager's thread. */
+ public void screenTurnedOff(boolean acquireSleepToken) {
synchronized (mLock) {
+ if (acquireSleepToken) {
+ mService.mRoot.mDisplayOffTokenAcquirer.acquire(mDisplayContent.mDisplayId);
+ }
mScreenOnEarly = false;
mScreenOnFully = false;
mKeyguardDrawComplete = false;
@@ -1036,7 +1049,7 @@
/**
* Check if a window can be added to the system.
*
- * Currently enforces that two window types are singletons per display:
+ * Currently enforces that these window types are singletons per display:
* <ul>
* <li>{@link WindowManager.LayoutParams#TYPE_STATUS_BAR}</li>
* <li>{@link WindowManager.LayoutParams#TYPE_NOTIFICATION_SHADE}</li>
@@ -1058,41 +1071,39 @@
ActivityTaskManagerService.enforceTaskPermission("DisplayPolicy");
}
+ final String systemUiPermission =
+ mService.isCallerVirtualDeviceOwner(mDisplayContent.getDisplayId(), callingUid)
+ // Allow virtual device owners to add system windows on their displays.
+ ? android.Manifest.permission.CREATE_VIRTUAL_DEVICE
+ : android.Manifest.permission.STATUS_BAR_SERVICE;
+
switch (attrs.type) {
case TYPE_STATUS_BAR:
- mContext.enforcePermission(
- android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
+ mContext.enforcePermission(systemUiPermission, callingPid, callingUid,
"DisplayPolicy");
if (mStatusBar != null && mStatusBar.isAlive()) {
return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
}
break;
case TYPE_NOTIFICATION_SHADE:
- mContext.enforcePermission(
- android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
+ mContext.enforcePermission(systemUiPermission, callingPid, callingUid,
"DisplayPolicy");
- if (mNotificationShade != null) {
- if (mNotificationShade.isAlive()) {
- return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
- }
+ if (mNotificationShade != null && mNotificationShade.isAlive()) {
+ return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
}
break;
case TYPE_NAVIGATION_BAR:
- mContext.enforcePermission(android.Manifest.permission.STATUS_BAR_SERVICE,
- callingPid, callingUid, "DisplayPolicy");
+ mContext.enforcePermission(systemUiPermission, callingPid, callingUid,
+ "DisplayPolicy");
if (mNavigationBar != null && mNavigationBar.isAlive()) {
return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
}
break;
case TYPE_NAVIGATION_BAR_PANEL:
- mContext.enforcePermission(android.Manifest.permission.STATUS_BAR_SERVICE,
- callingPid, callingUid, "DisplayPolicy");
- break;
case TYPE_STATUS_BAR_ADDITIONAL:
case TYPE_STATUS_BAR_SUB_PANEL:
case TYPE_VOICE_INTERACTION_STARTING:
- mContext.enforcePermission(
- android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
+ mContext.enforcePermission(systemUiPermission, callingPid, callingUid,
"DisplayPolicy");
break;
case TYPE_STATUS_BAR_PANEL:
@@ -1102,8 +1113,7 @@
if (attrs.providedInsets != null) {
// Recents component is allowed to add inset types.
if (!mService.mAtmService.isCallerRecents(callingUid)) {
- mContext.enforcePermission(
- android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
+ mContext.enforcePermission(systemUiPermission, callingPid, callingUid,
"DisplayPolicy");
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index f40f2617..e585efa 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -69,6 +69,7 @@
mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
}
+ /** Stores the size override settings. If the width or height is zero, it means to clear. */
void setForcedSize(@NonNull DisplayContent displayContent, int width, int height) {
if (displayContent.isDefaultDisplay) {
final String sizeString = (width == 0 || height == 0) ? "" : (width + "," + height);
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 59435b8..b09d63f 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -175,7 +175,7 @@
*/
private CompletableFuture<Void> showInputSurface() {
if (mInputSurface == null) {
- mInputSurface = mService.makeSurfaceBuilder(mDisplayContent.getSession())
+ mInputSurface = mService.makeSurfaceBuilder()
.setContainerLayer()
.setName("Drag and Drop Input Consumer")
.setCallsite("DragState.showInputSurface")
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index 6b916ef..43c3d05 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -104,7 +104,7 @@
mGivenInsetsReady = true;
ImeTracker.forLogging().onProgress(mStatsToken,
ImeTracker.PHASE_WM_POST_LAYOUT_NOTIFY_CONTROLS_CHANGED);
- mStateController.notifyControlChanged(mControlTarget);
+ mStateController.notifyControlChanged(mControlTarget, this);
setImeShowing(true);
} else if (wasServerVisible && mServerVisible && mGivenInsetsReady
&& givenInsetsPending) {
@@ -132,15 +132,15 @@
}
@Override
- protected boolean isLeashReadyForDispatching() {
+ protected boolean isLeashReadyForDispatching(InsetsControlTarget target) {
if (android.view.inputmethod.Flags.refactorInsetsController()) {
final WindowState ws =
mWindowContainer != null ? mWindowContainer.asWindowState() : null;
final boolean isDrawn = ws != null && ws.isDrawn();
- return super.isLeashReadyForDispatching() && mServerVisible && isDrawn
- && mGivenInsetsReady;
+ return super.isLeashReadyForDispatching(target)
+ && mServerVisible && isDrawn && mGivenInsetsReady;
} else {
- return super.isLeashReadyForDispatching();
+ return super.isLeashReadyForDispatching(target);
}
}
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index 4204670..a288cc7 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -77,8 +77,7 @@
mWindowHandle.scaleFactor = 1.0f;
mWindowHandle.inputConfig = InputConfig.NOT_FOCUSABLE;
- mInputSurface = mService.makeSurfaceBuilder(
- mService.mRoot.getDisplayContent(displayId).getSession())
+ mInputSurface = mService.makeSurfaceBuilder()
.setContainerLayer()
.setName("Input Consumer " + name)
.setCallsite("InputConsumerImpl")
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index 1e7de2b..232c3b6 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -281,7 +281,7 @@
+ " - Input overlay layer is not initialized.");
return null;
}
- return mService.makeSurfaceBuilder(dc.getSession())
+ return mService.makeSurfaceBuilder()
.setContainerLayer()
.setName(name)
.setCallsite("createSurfaceForGestureMonitor")
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index b66b8bc..8f90b2d 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -411,7 +411,7 @@
changed = true;
}
if (changed) {
- mStateController.notifyControlChanged(mControlTarget);
+ mStateController.notifyControlChanged(mControlTarget, this);
}
}
@@ -556,11 +556,37 @@
}
mControl = new InsetsSourceControl(mSource.getId(), mSource.getType(), leash,
initiallyVisible, surfacePosition, getInsetsHint());
+ mStateController.notifySurfaceTransactionReady(this, getSurfaceTransactionId(leash), true);
ProtoLog.d(WM_DEBUG_WINDOW_INSETS,
"InsetsSource Control %s for target %s", mControl, mControlTarget);
}
+ private long getSurfaceTransactionId(SurfaceControl leash) {
+ // Here returns mNativeObject (long) as the ID instead of the leash itself so that
+ // InsetsStateController won't keep referencing the leash unexpectedly.
+ return leash != null ? leash.mNativeObject : 0;
+ }
+
+ /**
+ * This is called when the surface transaction of the leash initialization has been committed.
+ *
+ * @param id Indicates which transaction is committed so that stale callbacks can be dropped.
+ */
+ void onSurfaceTransactionCommitted(long id) {
+ if (mIsLeashReadyForDispatching) {
+ return;
+ }
+ if (mControl == null) {
+ return;
+ }
+ if (id != getSurfaceTransactionId(mControl.getLeash())) {
+ return;
+ }
+ mIsLeashReadyForDispatching = true;
+ mStateController.notifySurfaceTransactionReady(this, 0, false);
+ }
+
void startSeamlessRotation() {
if (!mSeamlessRotating) {
mSeamlessRotating = true;
@@ -582,10 +608,6 @@
return true;
}
- void onSurfaceTransactionApplied() {
- mIsLeashReadyForDispatching = true;
- }
-
void setClientVisible(boolean clientVisible) {
if (mClientVisible == clientVisible) {
return;
@@ -612,8 +634,9 @@
mServerVisible, mClientVisible);
}
- protected boolean isLeashReadyForDispatching() {
- return mIsLeashReadyForDispatching;
+ protected boolean isLeashReadyForDispatching(InsetsControlTarget target) {
+ // If the target is not the control target, we are ready for dispatching a null-leash to it.
+ return target != mControlTarget || mIsLeashReadyForDispatching;
}
/**
@@ -626,7 +649,7 @@
@Nullable
InsetsSourceControl getControl(InsetsControlTarget target) {
if (target == mControlTarget) {
- if (!isLeashReadyForDispatching() && mControl != null) {
+ if (!isLeashReadyForDispatching(target) && mControl != null) {
// The surface transaction of preparing leash is not applied yet. We don't send it
// to the client in case that the client applies its transaction sooner than ours
// that we could unexpectedly overwrite the surface state.
@@ -799,6 +822,7 @@
public void onAnimationCancelled(SurfaceControl animationLeash) {
if (mAdapter == this) {
mStateController.notifyControlRevoked(mControlTarget, InsetsSourceProvider.this);
+ mStateController.notifySurfaceTransactionReady(InsetsSourceProvider.this, 0, false);
mControl = null;
mControlTarget = null;
mAdapter = null;
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 098a691..0daddc0 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -34,6 +34,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.SparseArray;
+import android.util.SparseLongArray;
import android.util.proto.ProtoOutputStream;
import android.view.InsetsSource;
import android.view.InsetsSourceControl;
@@ -59,13 +60,14 @@
private final DisplayContent mDisplayContent;
private final SparseArray<InsetsSourceProvider> mProviders = new SparseArray<>();
+ private final SparseLongArray mSurfaceTransactionIds = new SparseLongArray();
private final ArrayMap<InsetsControlTarget, ArrayList<InsetsSourceProvider>>
mControlTargetProvidersMap = new ArrayMap<>();
+ private final ArrayMap<InsetsControlTarget, ArrayList<InsetsSourceProvider>>
+ mPendingTargetProvidersMap = new ArrayMap<>();
private final SparseArray<InsetsControlTarget> mIdControlTargetMap = new SparseArray<>();
private final SparseArray<InsetsControlTarget> mIdFakeControlTargetMap = new SparseArray<>();
- private final ArraySet<InsetsControlTarget> mPendingControlChanged = new ArraySet<>();
-
private final Consumer<WindowState> mDispatchInsetsChanged = w -> {
if (w.isReadyToDispatchInsetsState()) {
w.notifyInsetsChanged();
@@ -327,11 +329,11 @@
}
if (lastTarget != null) {
removeFromControlMaps(lastTarget, provider, fake);
- mPendingControlChanged.add(lastTarget);
+ addToPendingControlMaps(lastTarget, provider);
}
if (target != null) {
addToControlMaps(target, provider, fake);
- mPendingControlChanged.add(target);
+ addToPendingControlMaps(target, provider);
}
}
@@ -364,8 +366,15 @@
}
}
- void notifyControlChanged(InsetsControlTarget target) {
- mPendingControlChanged.add(target);
+ private void addToPendingControlMaps(@NonNull InsetsControlTarget target,
+ InsetsSourceProvider provider) {
+ final ArrayList<InsetsSourceProvider> array =
+ mPendingTargetProvidersMap.computeIfAbsent(target, key -> new ArrayList<>());
+ array.add(provider);
+ }
+
+ void notifyControlChanged(InsetsControlTarget target, InsetsSourceProvider provider) {
+ addToPendingControlMaps(target, provider);
notifyPendingInsetsControlChanged();
if (android.view.inputmethod.Flags.refactorInsetsController()) {
@@ -376,26 +385,58 @@
}
}
+ void notifySurfaceTransactionReady(InsetsSourceProvider provider, long id, boolean ready) {
+ if (ready) {
+ mSurfaceTransactionIds.put(provider.getSource().getId(), id);
+ } else {
+ mSurfaceTransactionIds.delete(provider.getSource().getId());
+ }
+ }
+
private void notifyPendingInsetsControlChanged() {
- if (mPendingControlChanged.isEmpty()) {
+ if (mPendingTargetProvidersMap.isEmpty()) {
return;
}
+ final int size = mSurfaceTransactionIds.size();
+ final SparseLongArray surfaceTransactionIds = new SparseLongArray(size);
+ for (int i = 0; i < size; i++) {
+ surfaceTransactionIds.append(
+ mSurfaceTransactionIds.keyAt(i), mSurfaceTransactionIds.valueAt(i));
+ }
mDisplayContent.mWmService.mAnimator.addAfterPrepareSurfacesRunnable(() -> {
- for (int i = mProviders.size() - 1; i >= 0; i--) {
- final InsetsSourceProvider provider = mProviders.valueAt(i);
- provider.onSurfaceTransactionApplied();
+ for (int i = 0; i < size; i++) {
+ final int sourceId = surfaceTransactionIds.keyAt(i);
+ final InsetsSourceProvider provider = mProviders.get(sourceId);
+ if (provider == null) {
+ continue;
+ }
+ provider.onSurfaceTransactionCommitted(surfaceTransactionIds.valueAt(i));
}
final ArraySet<InsetsControlTarget> newControlTargets = new ArraySet<>();
int displayId = mDisplayContent.getDisplayId();
- for (int i = mPendingControlChanged.size() - 1; i >= 0; i--) {
- final InsetsControlTarget controlTarget = mPendingControlChanged.valueAt(i);
- controlTarget.notifyInsetsControlChanged(displayId);
- if (mControlTargetProvidersMap.containsKey(controlTarget)) {
- // We only collect targets who get controls, not lose controls.
- newControlTargets.add(controlTarget);
+ final ArrayMap<InsetsControlTarget, ArrayList<InsetsSourceProvider>> pendingControlMap =
+ mPendingTargetProvidersMap;
+ for (int i = pendingControlMap.size() - 1; i >= 0; i--) {
+ final InsetsControlTarget target = pendingControlMap.keyAt(i);
+ final ArrayList<InsetsSourceProvider> providers = pendingControlMap.valueAt(i);
+ for (int p = providers.size() - 1; p >= 0; p--) {
+ final InsetsSourceProvider provider = providers.get(p);
+ if (provider.isLeashReadyForDispatching(target)) {
+ // Stop waiting for this provider.
+ providers.remove(p);
+ }
+ }
+ if (providers.isEmpty()) {
+ pendingControlMap.removeAt(i);
+
+ // All controls of this target are ready to be dispatched.
+ target.notifyInsetsControlChanged(displayId);
+ if (mControlTargetProvidersMap.containsKey(target)) {
+ // We only collect targets who get controls, not lose controls.
+ newControlTargets.add(target);
+ }
}
}
- mPendingControlChanged.clear();
// This updates the insets visibilities AFTER sending current insets state and controls
// to the clients, so that the clients can change the current visibilities to the
@@ -424,7 +465,7 @@
* @param target the control target to check.
*/
boolean hasPendingControls(@NonNull InsetsControlTarget target) {
- return mPendingControlChanged.contains(target);
+ return mPendingTargetProvidersMap.containsKey(target);
}
void dump(String prefix, PrintWriter pw) {
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 5d8a96c..0c489d6 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -87,7 +87,7 @@
private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>();
private final ActivityTaskManagerService mService;
private RootWindowContainer mRootWindowContainer;
- private final ActivityTaskManagerInternal.SleepTokenAcquirer mSleepTokenAcquirer;
+ private final ActivityTaskManagerService.SleepTokenAcquirer mSleepTokenAcquirer;
private boolean mWaitingForWakeTransition;
private Transition.ReadyCondition mWaitAodHide = null;
@@ -95,7 +95,7 @@
ActivityTaskSupervisor taskSupervisor) {
mService = service;
mTaskSupervisor = taskSupervisor;
- mSleepTokenAcquirer = mService.new SleepTokenAcquirerImpl(KEYGUARD_SLEEP_TOKEN_TAG);
+ mSleepTokenAcquirer = mService.new SleepTokenAcquirer(KEYGUARD_SLEEP_TOKEN_TAG);
}
void setWindowManager(WindowManagerService windowManager) {
@@ -658,10 +658,10 @@
private boolean mRequestDismissKeyguard;
private final ActivityTaskManagerService mService;
- private final ActivityTaskManagerInternal.SleepTokenAcquirer mSleepTokenAcquirer;
+ private final ActivityTaskManagerService.SleepTokenAcquirer mSleepTokenAcquirer;
KeyguardDisplayState(ActivityTaskManagerService service, int displayId,
- ActivityTaskManagerInternal.SleepTokenAcquirer acquirer) {
+ ActivityTaskManagerService.SleepTokenAcquirer acquirer) {
mService = service;
mDisplayId = displayId;
mSleepTokenAcquirer = acquirer;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 866dcd5..8f5612c 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -215,7 +215,7 @@
private static final String DISPLAY_OFF_SLEEP_TOKEN_TAG = "Display-off";
/** The token acquirer to put root tasks on the displays to sleep */
- final ActivityTaskManagerInternal.SleepTokenAcquirer mDisplayOffTokenAcquirer;
+ final ActivityTaskManagerService.SleepTokenAcquirer mDisplayOffTokenAcquirer;
/**
* The modes which affect which tasks are returned when calling
@@ -450,7 +450,7 @@
mService = service.mAtmService;
mTaskSupervisor = mService.mTaskSupervisor;
mTaskSupervisor.mRootWindowContainer = this;
- mDisplayOffTokenAcquirer = mService.new SleepTokenAcquirerImpl(DISPLAY_OFF_SLEEP_TOKEN_TAG);
+ mDisplayOffTokenAcquirer = mService.new SleepTokenAcquirer(DISPLAY_OFF_SLEEP_TOKEN_TAG);
mDeviceStateController = new DeviceStateController(service.mContext, service.mGlobalLock);
mDisplayRotationCoordinator = new DisplayRotationCoordinator();
}
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 7c875c1..2ea2aeb 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -38,7 +38,6 @@
import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
-import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -72,7 +71,6 @@
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
import android.view.View;
import android.view.View.FocusDirection;
import android.view.WindowInsets;
@@ -108,7 +106,6 @@
@NonNull
final WindowProcessController mProcess;
private final String mStringName;
- SurfaceSession mSurfaceSession;
private final ArrayList<WindowState> mAddedWindows = new ArrayList<>();
/** Set of visible alert/app-overlay windows connected to this session. */
private final ArraySet<WindowState> mAlertWindows = new ArraySet<>();
@@ -719,12 +716,10 @@
mPackageName = mProcess.mInfo.packageName;
mRelayoutTag = "relayoutWindow: " + mPackageName;
}
- if (mSurfaceSession == null) {
+ if (mProcess.mWindowSession == null) {
if (DEBUG) {
- Slog.v(TAG_WM, "First window added to " + this + ", creating SurfaceSession");
+ Slog.v(TAG_WM, "First window added to " + mProcess);
}
- mSurfaceSession = new SurfaceSession();
- ProtoLog.i(WM_SHOW_TRANSACTIONS, " NEW SURFACE SESSION %s", mSurfaceSession);
mService.mSessions.add(this);
if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
mService.dispatchNewAnimatorScaleLocked(this);
@@ -821,18 +816,11 @@
}
mService.mSessions.remove(this);
- if (mSurfaceSession == null) {
+ if (mProcess.mWindowSession == null) {
return;
}
- ProtoLog.i(WM_SHOW_TRANSACTIONS, " KILL SURFACE SESSION %s", mSurfaceSession);
- try {
- mSurfaceSession.kill();
- } catch (Exception e) {
- Slog.w(TAG_WM, "Exception thrown when killing surface session " + mSurfaceSession
- + " in session " + this + ": " + e.toString());
- }
- mSurfaceSession = null;
+ mProcess.mWindowSession = null;
mAddedWindows.clear();
mAlertWindows.clear();
setHasOverlayUi(false);
@@ -857,7 +845,6 @@
pw.print(" mCanAddInternalSystemWindow="); pw.print(mCanAddInternalSystemWindow);
pw.print(" mAlertWindows="); pw.print(mAlertWindows);
pw.print(" mClientDead="); pw.print(mClientDead);
- pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
pw.print(prefix); pw.print("mPackageName="); pw.println(mPackageName);
if (isSatellitePointingUiPackage()) {
pw.print(prefix); pw.println("mIsSatellitePointingUiPackage=true");
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 21be0fc..8c93b4fe 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3507,7 +3507,7 @@
* {@link android.window.TaskFragmentOrganizer}
*/
TaskFragmentParentInfo getTaskFragmentParentInfo() {
- return new TaskFragmentParentInfo(getConfiguration(), getDisplayId(),
+ return new TaskFragmentParentInfo(getConfiguration(), getDisplayId(), mTaskId,
shouldBeVisible(null /* starting */), hasNonFinishingDirectActivity(),
getDecorSurface());
}
diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
index 5aa34d2..92953e5 100644
--- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
@@ -17,6 +17,8 @@
package com.android.server.wm;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.window.TaskFragmentOrganizer.KEY_RESTORE_TASK_FRAGMENTS_INFO;
+import static android.window.TaskFragmentOrganizer.KEY_RESTORE_TASK_FRAGMENT_PARENT_INFO;
import static android.window.TaskFragmentOrganizer.putErrorInfoInBundle;
import static android.window.TaskFragmentTransaction.TYPE_ACTIVITY_REPARENTED_TO_TASK;
import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_APPEARED;
@@ -206,7 +208,13 @@
mOrganizerPid = pid;
mAppThread = getAppThread(pid, mOrganizerUid);
for (int i = mOrganizedTaskFragments.size() - 1; i >= 0; i--) {
- mOrganizedTaskFragments.get(i).onTaskFragmentOrganizerRestarted(organizer);
+ final TaskFragment taskFragment = mOrganizedTaskFragments.get(i);
+ if (taskFragment.isAttached()
+ && taskFragment.getTopNonFinishingActivity() != null) {
+ taskFragment.onTaskFragmentOrganizerRestarted(organizer);
+ } else {
+ mOrganizedTaskFragments.remove(taskFragment);
+ }
}
try {
mOrganizer.asBinder().linkToDeath(this, 0 /*flags*/);
@@ -575,8 +583,29 @@
}
mCachedTaskFragmentOrganizerStates.remove(cachedState);
- outSavedState.putAll(cachedState.mSavedState);
cachedState.restore(organizer, pid);
+ outSavedState.putAll(cachedState.mSavedState);
+
+ // Collect the organized TfInfo and TfParentInfo in the system.
+ final ArrayList<TaskFragmentInfo> infos = new ArrayList<>();
+ final ArrayMap<Integer, Task> tasks = new ArrayMap<>();
+ final int fragmentCount = cachedState.mOrganizedTaskFragments.size();
+ for (int j = 0; j < fragmentCount; j++) {
+ final TaskFragment tf = cachedState.mOrganizedTaskFragments.get(j);
+ infos.add(tf.getTaskFragmentInfo());
+ if (!tasks.containsKey(tf.getTask().mTaskId)) {
+ tasks.put(tf.getTask().mTaskId, tf.getTask());
+ }
+ }
+ outSavedState.putParcelableArrayList(KEY_RESTORE_TASK_FRAGMENTS_INFO, infos);
+
+ final ArrayList<TaskFragmentParentInfo> parentInfos = new ArrayList<>();
+ for (int j = tasks.size() - 1; j >= 0; j--) {
+ parentInfos.add(tasks.valueAt(j).getTaskFragmentParentInfo());
+ }
+ outSavedState.putParcelableArrayList(KEY_RESTORE_TASK_FRAGMENT_PARENT_INFO,
+ parentInfos);
+
mTaskFragmentOrganizerState.put(organizer.asBinder(), cachedState);
mPendingTaskFragmentEvents.put(organizer.asBinder(), new ArrayList<>());
return true;
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 7f6dc84..e6226ab 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -953,13 +953,10 @@
* Set animation options for collecting transition by ActivityRecord.
* @param options AnimationOptions captured from ActivityOptions
*/
- void setOverrideAnimation(@Nullable AnimationOptions options, @NonNull ActivityRecord r,
+ void setOverrideAnimation(@Nullable AnimationOptions options,
@Nullable IRemoteCallback startCallback, @Nullable IRemoteCallback finishCallback) {
if (!isCollecting()) return;
mOverrideOptions = options;
- if (mOverrideOptions != null) {
- mOverrideOptions.setUserId(r.mUserId);
- }
sendRemoteCallback(mClientAnimationStartCallback);
mClientAnimationStartCallback = startCallback;
mClientAnimationFinishCallback = finishCallback;
@@ -2822,7 +2819,7 @@
}
}
final SurfaceControl rootLeash = leashReference.makeAnimationLeash().setName(
- "Transition Root: " + leashReference.getName())
+ "Transition Root: " + leashReference.getName())
.setCallsite("Transition.calculateTransitionRoots").build();
rootLeash.setUnreleasedWarningCallSite("Transition.calculateTransitionRoots");
// Update layers to start transaction because we prevent assignment during collect, so
@@ -2993,8 +2990,7 @@
// Create the options based on this change's custom animations and layout
// parameters
animOptions = getOptions(activityRecord /* customAnimActivity */,
- activityRecord /* animLpActivity */);
- animOptions.setUserId(activityRecord.mUserId);
+ activityRecord /* animLpActivity */);
if (!change.hasFlags(FLAG_TRANSLUCENT)) {
// If this change is not translucent, its options are going to be
// inherited by the changes below
@@ -3004,7 +3000,6 @@
} else if (activityRecord != null && animOptionsForActivityTransition != null) {
// Use the same options from the top activity for all the activities
animOptions = animOptionsForActivityTransition;
- animOptions.setUserId(activityRecord.mUserId);
} else if (Flags.activityEmbeddingOverlayPresentationFlag()
&& isEmbeddedTaskFragment) {
final TaskFragmentAnimationParams params = taskFragment.getAnimationParams();
@@ -3017,7 +3012,6 @@
params.getOpenAnimationResId(), params.getChangeAnimationResId(),
params.getCloseAnimationResId(), 0 /* backgroundColor */,
false /* overrideTaskTransition */);
- animOptions.setUserId(taskFragment.getTask().mUserId);
}
}
if (animOptions != null) {
@@ -3081,9 +3075,6 @@
animOptions);
animOptions = addCustomActivityTransition(customAnimActivity, false /* open */,
animOptions);
- if (animOptions != null) {
- animOptions.setUserId(customAnimActivity.mUserId);
- }
}
// Layout parameters
@@ -3097,12 +3088,10 @@
// are running an app starting animation, in which case we don't want the app to be
// able to change its animation directly.
if (animOptions != null) {
- animOptions.setUserId(animLpActivity.mUserId);
animOptions.addOptionsFromLayoutParameters(animLp);
} else {
animOptions = TransitionInfo.AnimationOptions
.makeAnimOptionsFromLayoutParameters(animLp);
- animOptions.setUserId(animLpActivity.mUserId);
}
}
return animOptions;
@@ -3128,7 +3117,6 @@
if (animOptions == null) {
animOptions = TransitionInfo.AnimationOptions
.makeCommonAnimOptions(activity.packageName);
- animOptions.setUserId(activity.mUserId);
}
animOptions.addCustomActivityTransition(open, customAnim.mEnterAnim,
customAnim.mExitAnim, customAnim.mBackgroundColor);
@@ -3257,7 +3245,7 @@
// Remote animations always win, but fullscreen windows override non-fullscreen windows.
ActivityRecord result = lookForTopWindowWithFilter(sortedTargets,
w -> w.getRemoteAnimationDefinition() != null
- && w.getRemoteAnimationDefinition().hasTransition(transit, activityTypes));
+ && w.getRemoteAnimationDefinition().hasTransition(transit, activityTypes));
if (result != null) {
return result;
}
@@ -3304,7 +3292,7 @@
private void validateKeyguardOcclusion() {
if ((mFlags & KEYGUARD_VISIBILITY_TRANSIT_FLAGS) != 0) {
mController.mStateValidators.add(
- mController.mAtm.mWindowManager.mPolicy::applyKeyguardOcclusionChange);
+ mController.mAtm.mWindowManager.mPolicy::applyKeyguardOcclusionChange);
}
}
@@ -3913,9 +3901,9 @@
/** @return true if all tracked subtrees are ready. */
boolean allReady() {
- ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
- " allReady query: used=%b " + "override=%b defer=%d states=[%s]", mUsed,
- mReadyOverride, mDeferReadyDepth, groupsToString());
+ ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " allReady query: used=%b "
+ + "override=%b defer=%d states=[%s]", mUsed, mReadyOverride, mDeferReadyDepth,
+ groupsToString());
// If the readiness has never been touched, mUsed will be false. We never want to
// consider a transition ready if nothing has been reported on it.
if (!mUsed) return false;
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 1d2a605..50fe69c 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -52,8 +52,8 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.protolog.ProtoLog;
import com.android.internal.protolog.ProtoLogGroup;
+import com.android.internal.protolog.ProtoLog;
import com.android.server.FgThread;
import com.android.window.flags.Flags;
@@ -880,10 +880,10 @@
}
/** @see Transition#setOverrideAnimation */
- void setOverrideAnimation(TransitionInfo.AnimationOptions options, ActivityRecord r,
+ void setOverrideAnimation(TransitionInfo.AnimationOptions options,
@Nullable IRemoteCallback startCallback, @Nullable IRemoteCallback finishCallback) {
if (mCollectingTransition == null) return;
- mCollectingTransition.setOverrideAnimation(options, r, startCallback, finishCallback);
+ mCollectingTransition.setOverrideAnimation(options, startCallback, finishCallback);
}
void setNoAnimation(WindowContainer wc) {
diff --git a/services/core/java/com/android/server/wm/TrustedOverlayHost.java b/services/core/java/com/android/server/wm/TrustedOverlayHost.java
index 5f3c558..030e848 100644
--- a/services/core/java/com/android/server/wm/TrustedOverlayHost.java
+++ b/services/core/java/com/android/server/wm/TrustedOverlayHost.java
@@ -51,7 +51,7 @@
void requireOverlaySurfaceControl() {
if (mSurfaceControl == null) {
- final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(null)
+ final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder()
.setContainerLayer()
.setHidden(true)
.setCallsite("TrustedOverlayHost.requireOverlaySurfaceControl")
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 13334a5..2342de3 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -27,6 +27,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.content.Context;
+import android.os.HandlerExecutor;
import android.os.Trace;
import android.util.Slog;
import android.util.TimeUtils;
@@ -68,6 +69,8 @@
private Choreographer mChoreographer;
+ private final HandlerExecutor mExecutor;
+
/**
* Indicates whether we have an animation frame callback scheduled, which will happen at
* vsync-app and then schedule the animation tick at the right time (vsync-sf).
@@ -79,8 +82,7 @@
* A list of runnable that need to be run after {@link WindowContainer#prepareSurfaces} is
* executed and the corresponding transaction is closed and applied.
*/
- private final ArrayList<Runnable> mAfterPrepareSurfacesRunnables = new ArrayList<>();
- private boolean mInExecuteAfterPrepareSurfacesRunnables;
+ private ArrayList<Runnable> mAfterPrepareSurfacesRunnables = new ArrayList<>();
private final SurfaceControl.Transaction mTransaction;
@@ -91,6 +93,7 @@
mTransaction = service.mTransactionFactory.get();
service.mAnimationHandler.runWithScissors(
() -> mChoreographer = Choreographer.getSfInstance(), 0 /* timeout */);
+ mExecutor = new HandlerExecutor(service.mAnimationHandler);
mAnimationFrameCallback = frameTimeNs -> {
synchronized (mService.mGlobalLock) {
@@ -198,6 +201,19 @@
updateRunningExpensiveAnimationsLegacy();
}
+ final ArrayList<Runnable> afterPrepareSurfacesRunnables = mAfterPrepareSurfacesRunnables;
+ if (!afterPrepareSurfacesRunnables.isEmpty()) {
+ mAfterPrepareSurfacesRunnables = new ArrayList<>();
+ mTransaction.addTransactionCommittedListener(mExecutor, () -> {
+ synchronized (mService.mGlobalLock) {
+ // Traverse in order they were added.
+ for (int i = 0, size = afterPrepareSurfacesRunnables.size(); i < size; i++) {
+ afterPrepareSurfacesRunnables.get(i).run();
+ }
+ afterPrepareSurfacesRunnables.clear();
+ }
+ });
+ }
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "applyTransaction");
mTransaction.apply();
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
@@ -205,7 +221,6 @@
ProtoLog.i(WM_SHOW_TRANSACTIONS, "<<< CLOSE TRANSACTION animate");
mService.mAtmService.mTaskOrganizerController.dispatchPendingEvents();
- executeAfterPrepareSurfacesRunnables();
if (DEBUG_WINDOW_TRACE) {
Slog.i(TAG, "!!! animate: exit"
@@ -287,34 +302,10 @@
/**
* Adds a runnable to be executed after {@link WindowContainer#prepareSurfaces} is called and
- * the corresponding transaction is closed and applied.
+ * the corresponding transaction is closed, applied, and committed.
*/
void addAfterPrepareSurfacesRunnable(Runnable r) {
- // If runnables are already being handled in executeAfterPrepareSurfacesRunnable, then just
- // immediately execute the runnable passed in.
- if (mInExecuteAfterPrepareSurfacesRunnables) {
- r.run();
- return;
- }
-
mAfterPrepareSurfacesRunnables.add(r);
scheduleAnimation();
}
-
- void executeAfterPrepareSurfacesRunnables() {
-
- // Don't even think about to start recursing!
- if (mInExecuteAfterPrepareSurfacesRunnables) {
- return;
- }
- mInExecuteAfterPrepareSurfacesRunnables = true;
-
- // Traverse in order they were added.
- final int size = mAfterPrepareSurfacesRunnables.size();
- for (int i = 0; i < size; i++) {
- mAfterPrepareSurfacesRunnables.get(i).run();
- }
- mAfterPrepareSurfacesRunnables.clear();
- mInExecuteAfterPrepareSurfacesRunnables = false;
- }
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 790ca1b..1eeb3ec 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -100,7 +100,6 @@
import android.view.SurfaceControl;
import android.view.SurfaceControl.Builder;
import android.view.SurfaceControlViewHost;
-import android.view.SurfaceSession;
import android.view.WindowManager;
import android.view.WindowManager.TransitionOldType;
import android.view.animation.Animation;
@@ -706,7 +705,7 @@
mLastSurfacePosition.set(0, 0);
mLastDeltaRotation = Surface.ROTATION_0;
- final Builder b = mWmService.makeSurfaceBuilder(null)
+ final Builder b = mWmService.makeSurfaceBuilder()
.setContainerLayer()
.setName(getName());
@@ -2662,13 +2661,6 @@
return true;
}
- SurfaceSession getSession() {
- if (getParent() != null) {
- return getParent().getSession();
- }
- return null;
- }
-
void assignLayer(Transaction t, int layer) {
// Don't assign layers while a transition animation is playing
// TODO(b/173528115): establish robust best-practices around z-order fighting.
diff --git a/services/core/java/com/android/server/wm/WindowManagerConstants.java b/services/core/java/com/android/server/wm/WindowManagerConstants.java
index 47c42f4..e0f24d8 100644
--- a/services/core/java/com/android/server/wm/WindowManagerConstants.java
+++ b/services/core/java/com/android/server/wm/WindowManagerConstants.java
@@ -34,7 +34,7 @@
*/
final class WindowManagerConstants {
- /** The orientation of activity will be always "unspecified". */
+ /** The orientation of activity will be always "unspecified" except for game apps. */
private static final String KEY_IGNORE_ACTIVITY_ORIENTATION_REQUEST =
"ignore_activity_orientation_request";
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 29ab4dd..fb57a1b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -288,7 +288,6 @@
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
-import android.view.SurfaceSession;
import android.view.View;
import android.view.View.FocusDirection;
import android.view.ViewDebug;
@@ -386,7 +385,6 @@
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import java.util.function.Function;
import java.util.function.Supplier;
/** {@hide} */
@@ -1111,7 +1109,7 @@
static WindowManagerThreadPriorityBooster sThreadPriorityBooster =
new WindowManagerThreadPriorityBooster();
- Function<SurfaceSession, SurfaceControl.Builder> mSurfaceControlFactory;
+ Supplier<SurfaceControl.Builder> mSurfaceControlFactory;
Supplier<SurfaceControl.Transaction> mTransactionFactory;
private final SurfaceControl.Transaction mTransaction;
@@ -1202,7 +1200,7 @@
final boolean showBootMsgs, WindowManagerPolicy policy, ActivityTaskManagerService atm,
DisplayWindowSettingsProvider displayWindowSettingsProvider,
Supplier<SurfaceControl.Transaction> transactionFactory,
- Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
+ Supplier<SurfaceControl.Builder> surfaceControlFactory) {
final WindowManagerService[] wms = new WindowManagerService[1];
DisplayThread.getHandler().runWithScissors(() ->
wms[0] = new WindowManagerService(context, im, showBootMsgs, policy, atm,
@@ -1231,7 +1229,7 @@
boolean showBootMsgs, WindowManagerPolicy policy, ActivityTaskManagerService atm,
DisplayWindowSettingsProvider displayWindowSettingsProvider,
Supplier<SurfaceControl.Transaction> transactionFactory,
- Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
+ Supplier<SurfaceControl.Builder> surfaceControlFactory) {
installLock(this, INDEX_WINDOW);
mGlobalLock = atm.getGlobalLock();
mAtmService = atm;
@@ -1526,7 +1524,7 @@
final boolean isRoundedCornerOverlay = (attrs.privateFlags
& PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0;
int res = mPolicy.checkAddPermission(attrs.type, isRoundedCornerOverlay, attrs.packageName,
- appOp);
+ appOp, displayId);
if (res != ADD_OKAY) {
return res;
}
@@ -6025,7 +6023,7 @@
displayContent.setForcedSize(displayContent.mInitialDisplayWidth,
displayContent.mInitialDisplayHeight,
displayContent.mInitialPhysicalXDpi,
- displayContent.mInitialPhysicalXDpi);
+ displayContent.mInitialPhysicalYDpi);
}
}
} finally {
@@ -8521,7 +8519,7 @@
return null;
}
// TODO(b/210039666): Use a method like add/removeDisplayOverlay if available.
- return makeSurfaceBuilder(dc.getSession())
+ return makeSurfaceBuilder()
.setContainerLayer()
.setName("IME Handwriting Surface")
.setCallsite("getHandwritingSurfaceForDisplay")
@@ -8829,8 +8827,8 @@
}
}
- SurfaceControl.Builder makeSurfaceBuilder(SurfaceSession s) {
- return mSurfaceControlFactory.apply(s);
+ SurfaceControl.Builder makeSurfaceBuilder() {
+ return mSurfaceControlFactory.get();
}
/**
@@ -10123,6 +10121,23 @@
}
}
+ /**
+ * Returns whether the given UID is the owner of a virtual device, which the given display
+ * belongs to.
+ */
+ @Override
+ public boolean isCallerVirtualDeviceOwner(int displayId, int callingUid) {
+ if (!android.companion.virtualdevice.flags.Flags.statusBarAndInsets()) {
+ return false;
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return mAtmService.mTaskSupervisor.isDeviceOwnerUid(displayId, callingUid);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
@RequiresPermission(ACCESS_SURFACE_FLINGER)
@Override
public boolean replaceContentOnDisplay(int displayId, SurfaceControl sc) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index b6b36c7..87ce866 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -358,7 +358,6 @@
mUseFifoUiScheduling = com.android.window.flags.Flags.fifoPriorityForMajorUiProcesses()
&& (isSysUiPackage || mAtm.isCallerRecents(uid));
- onConfigurationChanged(atm.getGlobalConfiguration());
mAtm.mPackageConfigPersister.updateConfigIfNeeded(this, mUserId, mInfo.packageName);
}
@@ -1926,7 +1925,12 @@
// showing.
// If the configuration has been overridden by previous activity, empty it.
mIsActivityConfigOverrideAllowed = false;
- unregisterActivityConfigurationListener();
+ // The call to `onServiceStarted` is not guarded with WM lock.
+ mAtm.mH.post(() -> {
+ synchronized (mAtm.mGlobalLock) {
+ unregisterActivityConfigurationListener();
+ }
+ });
break;
default:
break;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 7c05c29..256d0c6 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -233,7 +233,6 @@
import android.view.Surface;
import android.view.Surface.Rotation;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewTreeObserver;
@@ -5162,15 +5161,6 @@
}
@Override
- SurfaceSession getSession() {
- if (mSession.mSurfaceSession != null) {
- return mSession.mSurfaceSession;
- } else {
- return getParent().getSession();
- }
- }
-
- @Override
boolean needsZBoost() {
final InsetsControlTarget target = getDisplayContent().getImeTarget(IME_TARGET_LAYERING);
if (mIsImWindow && target != null) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index b40cf56..82fa9d4 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -321,8 +321,7 @@
}
if (DEBUG_VISIBILITY) {
- Slog.v(TAG, "Creating surface in session "
- + mSession.mSurfaceSession + " window " + this
+ Slog.v(TAG, "Creating surface " + this
+ " format=" + attrs.format + " flags=" + flags);
}
@@ -358,9 +357,8 @@
w.mInputWindowHandle.forceChange();
ProtoLog.i(WM_SHOW_SURFACE_ALLOC,
- " CREATE SURFACE %s IN SESSION %s: pid=%d format=%d flags=0x%x / %s",
- mSurfaceControl, mSession.mSurfaceSession, mSession.mPid, attrs.format,
- flags, this);
+ " CREATE SURFACE %s: pid=%d format=%d flags=0x%x / %s",
+ mSurfaceControl, mSession.mPid, attrs.format, flags, this);
} catch (OutOfResourcesException e) {
Slog.w(TAG, "OutOfResourcesException creating surface");
mService.mRoot.reclaimSomeSurfaceMemory(this, "create", true);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index fc61967..b6e45fc8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -7151,9 +7151,7 @@
// If there is a profile owner, redirect to that; otherwise query the device owner.
ComponentName aliasChooser = getProfileOwnerAsUser(caller.getUserId());
- boolean isDoUser = Flags.headlessSingleUserFixes()
- ? caller.getUserId() == getDeviceOwnerUserId()
- : caller.getUserHandle().isSystem();
+ boolean isDoUser = caller.getUserId() == getDeviceOwnerUserId();
if (aliasChooser == null && isDoUser) {
synchronized (getLockObject()) {
final ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdminLocked();
@@ -8163,7 +8161,7 @@
// First check whether the admin is allowed to wipe the device/user/profile.
final String restriction;
boolean shouldFactoryReset = userId == UserHandle.USER_SYSTEM;
- if (Flags.headlessSingleUserFixes() && getHeadlessDeviceOwnerModeForDeviceOwner()
+ if (getHeadlessDeviceOwnerModeForDeviceOwner()
== HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER) {
shouldFactoryReset = userId == getMainUserId();
}
@@ -8187,8 +8185,7 @@
adminPackage,
userId)) {
// Legacy mode
- wipeDevice = Flags.headlessSingleUserFixes()
- && getHeadlessDeviceOwnerModeForDeviceOwner()
+ wipeDevice = getHeadlessDeviceOwnerModeForDeviceOwner()
== HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER ? isMainUser : isSystemUser;
} else {
// Explicit behaviour
@@ -11858,7 +11855,7 @@
}
setBackwardsCompatibleAppRestrictions(
caller, packageName, restrictions, caller.getUserHandle());
- } else if (Flags.dmrhSetAppRestrictions()) {
+ } else {
final boolean isRoleHolder;
if (who != null) {
// DO or PO
@@ -11905,15 +11902,6 @@
caller.getUserHandle());
});
}
- } else {
- Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
- || (caller.hasPackage() && isCallerDelegate(caller,
- DELEGATION_APP_RESTRICTIONS)));
- mInjector.binderWithCleanCallingIdentity(() -> {
- mUserManager.setApplicationRestrictions(packageName, restrictions,
- caller.getUserHandle());
- });
}
DevicePolicyEventLogger
@@ -13244,7 +13232,7 @@
return Bundle.EMPTY;
}
return policies.get(enforcingAdmin).getValue();
- } else if (Flags.dmrhSetAppRestrictions()) {
+ } else {
final boolean isRoleHolder;
if (who != null) {
// Caller is DO or PO. They cannot call this on parent
@@ -13287,19 +13275,6 @@
return bundle != null ? bundle : Bundle.EMPTY;
});
}
-
- } else {
- Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
- || (caller.hasPackage() && isCallerDelegate(caller,
- DELEGATION_APP_RESTRICTIONS)));
- return mInjector.binderWithCleanCallingIdentity(() -> {
- Bundle bundle = mUserManager.getApplicationRestrictions(packageName,
- caller.getUserHandle());
- // if no restrictions were saved, mUserManager.getApplicationRestrictions
- // returns null, but DPM method should return an empty Bundle as per JavaDoc
- return bundle != null ? bundle : Bundle.EMPTY;
- });
}
}
@@ -14824,7 +14799,8 @@
}
@Override
- public void setSecondaryLockscreenEnabled(ComponentName who, boolean enabled) {
+ public void setSecondaryLockscreenEnabled(ComponentName who, boolean enabled,
+ PersistableBundle options) {
Objects.requireNonNull(who, "ComponentName is null");
// Check can set secondary lockscreen enabled
@@ -18662,19 +18638,16 @@
// Backup service has to be enabled on the main user in order for it to be enabled on
// secondary users.
- if (Flags.headlessSingleUserFixes() && isDeviceOwner(caller)
- && getHeadlessDeviceOwnerModeForDeviceOwner()
+ if (isDeviceOwner(caller) && getHeadlessDeviceOwnerModeForDeviceOwner()
== HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER) {
toggleBackupServiceActive(UserHandle.USER_SYSTEM, enabled);
}
toggleBackupServiceActive(caller.getUserId(), enabled);
- if (Flags.backupServiceSecurityLogEventEnabled()) {
- if (SecurityLog.isLoggingEnabled()) {
- SecurityLog.writeEvent(SecurityLog.TAG_BACKUP_SERVICE_TOGGLED,
- caller.getPackageName(), caller.getUserId(), enabled ? 1 : 0);
- }
+ if (SecurityLog.isLoggingEnabled()) {
+ SecurityLog.writeEvent(SecurityLog.TAG_BACKUP_SERVICE_TOGGLED,
+ caller.getPackageName(), caller.getUserId(), enabled ? 1 : 0);
}
}
@@ -21893,18 +21866,15 @@
return;
}
- if (Flags.copyAccountWithRetryEnabled()) {
- boolean copySucceeded = false;
- int retryAttemptsLeft = RETRY_COPY_ACCOUNT_ATTEMPTS;
- while (!copySucceeded && (retryAttemptsLeft > 0)) {
- Slogf.i(LOG_TAG, "Copying account. Attempts left : " + retryAttemptsLeft);
- copySucceeded =
- copyAccount(targetUser, sourceUser, accountToMigrate, callerPackage);
- retryAttemptsLeft--;
- }
- } else {
- copyAccount(targetUser, sourceUser, accountToMigrate, callerPackage);
+ boolean copySucceeded = false;
+ int retryAttemptsLeft = RETRY_COPY_ACCOUNT_ATTEMPTS;
+ while (!copySucceeded && (retryAttemptsLeft > 0)) {
+ Slogf.i(LOG_TAG, "Copying account. Attempts left : " + retryAttemptsLeft);
+ copySucceeded =
+ copyAccount(targetUser, sourceUser, accountToMigrate, callerPackage);
+ retryAttemptsLeft--;
}
+
if (!keepAccountMigrated) {
removeAccount(accountToMigrate, sourceUserId);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java b/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java
index 52a7845..87fd002 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java
@@ -361,9 +361,7 @@
@Override
boolean shouldWrite() {
- return Flags.alwaysPersistDo()
- || (mDeviceOwner != null) || (mSystemUpdatePolicy != null)
- || (mSystemUpdateInfo != null);
+ return true;
}
@Override
diff --git a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
index 7ed23cd..d2c91ff 100644
--- a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
@@ -888,7 +888,7 @@
val mayGrantByPrivileged =
!permission.isPrivileged ||
requestingPackageStates.anyIndexed { _, it ->
- checkPrivilegedPermissionAllowlist(it, permission)
+ checkPrivilegedPermissionAllowlistIfNeeded(it, permission)
}
val shouldGrantBySignature =
permission.isSignature &&
@@ -1280,7 +1280,16 @@
}
}
- private fun MutateStateScope.checkPrivilegedPermissionAllowlist(
+ /**
+ * We only check privileged permission allowlist for system privileged apps. Hence, for platform
+ * or for normal apps, we return true to indicate that we don't need to check the allowlist and
+ * will let follow-up checks to decide whether we should grant the permission.
+ *
+ * @return `true`, if the permission is allowlisted for system privileged apps, or if we
+ * don't need to check the allowlist (for platform or for normal apps).
+ * `false`, if the permission is not allowlisted for system privileged apps.
+ */
+ private fun MutateStateScope.checkPrivilegedPermissionAllowlistIfNeeded(
packageState: PackageState,
permission: Permission
): Boolean {
diff --git a/services/tests/InputMethodSystemServerTests/Android.bp b/services/tests/InputMethodSystemServerTests/Android.bp
index 3bce9b5..9044259 100644
--- a/services/tests/InputMethodSystemServerTests/Android.bp
+++ b/services/tests/InputMethodSystemServerTests/Android.bp
@@ -138,3 +138,17 @@
enabled: false,
},
}
+
+test_module_config {
+ name: "FrameworksInputMethodSystemServerTests_server_inputmethod",
+ base: "FrameworksInputMethodSystemServerTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.inputmethod"],
+}
+
+test_module_config {
+ name: "FrameworksImeTests_android_inputmethodservice",
+ base: "FrameworksImeTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.inputmethodservice"],
+}
diff --git a/services/tests/PackageManagerServiceTests/host/Android.bp b/services/tests/PackageManagerServiceTests/host/Android.bp
index 6fd21f7..75db316 100644
--- a/services/tests/PackageManagerServiceTests/host/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/Android.bp
@@ -88,3 +88,10 @@
" && $(location soong_zip) -o $(genDir)/temp.apk -L 0 -C $(genDir)/apk -D $(genDir)/apk" +
" && $(location zipalign) -f 4 $(genDir)/temp.apk $(out)",
}
+
+test_module_config_host {
+ name: "PackageManagerServiceHostTests_test_overlayactorvisibilitytest",
+ base: "PackageManagerServiceHostTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.pm.test.OverlayActorVisibilityTest"],
+}
diff --git a/services/tests/PackageManagerServiceTests/server/Android.bp b/services/tests/PackageManagerServiceTests/server/Android.bp
index 598e273..e26213e 100644
--- a/services/tests/PackageManagerServiceTests/server/Android.bp
+++ b/services/tests/PackageManagerServiceTests/server/Android.bp
@@ -164,3 +164,25 @@
"done && " +
"$(location soong_zip) -o $(out) -C $(genDir)/res -D $(genDir)/res",
}
+
+test_module_config {
+ name: "PackageManagerServiceServerTests_server_pm_Presubmit",
+ base: "PackageManagerServiceServerTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.pm."],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
+
+test_module_config {
+ name: "PackageManagerServiceServerTests_server_pm_Postsubmit",
+ base: "PackageManagerServiceServerTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.pm."],
+ include_annotations: ["android.platform.test.annotations.Postsubmit"],
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/Android.bp b/services/tests/PackageManagerServiceTests/unit/Android.bp
index c93f482..db88b16 100644
--- a/services/tests/PackageManagerServiceTests/unit/Android.bp
+++ b/services/tests/PackageManagerServiceTests/unit/Android.bp
@@ -47,3 +47,10 @@
platform_apis: true,
test_suites: ["device-tests"],
}
+
+test_module_config {
+ name: "PackageManagerServiceUnitTests_verify_domain",
+ base: "PackageManagerServiceUnitTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.pm.test.verify.domain"],
+}
diff --git a/services/tests/appfunctions/Android.bp b/services/tests/appfunctions/Android.bp
new file mode 100644
index 0000000..b5cf986
--- /dev/null
+++ b/services/tests/appfunctions/Android.bp
@@ -0,0 +1,59 @@
+// 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+ name: "FrameworksAppFunctionsTests",
+ team: "trendy_team_machine_learning",
+ defaults: [
+ "modules-utils-testable-device-config-defaults",
+ ],
+
+ srcs: [
+ "src/**/*.kt",
+ ],
+
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.runner",
+ "androidx.test.ext.truth",
+ "platform-test-annotations",
+ "services.appfunctions",
+ "servicestests-core-utils",
+ "truth",
+ "frameworks-base-testutils",
+ "androidx.test.rules",
+ ],
+
+ libs: [
+ "android.test.base",
+ "android.test.runner",
+ ],
+
+ certificate: "platform",
+ platform_apis: true,
+ test_suites: ["device-tests"],
+
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/services/tests/appfunctions/AndroidManifest.xml b/services/tests/appfunctions/AndroidManifest.xml
new file mode 100644
index 0000000..1d42b17
--- /dev/null
+++ b/services/tests/appfunctions/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.appfunctionstests">
+
+ <application android:testOnly="true"
+ android:debuggable="true">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.frameworks.appfunctionstests"
+ android:label="Frameworks AppFunctions Services Tests" />
+
+</manifest>
\ No newline at end of file
diff --git a/services/tests/appfunctions/AndroidTest.xml b/services/tests/appfunctions/AndroidTest.xml
new file mode 100644
index 0000000..0650120
--- /dev/null
+++ b/services/tests/appfunctions/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+<configuration description="Runs Frameworks AppFunctions Services Tests.">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="install-arg" value="-t" />
+ <option name="test-file-name" value="FrameworksAppFunctionsTests.apk" />
+ </target_preparer>
+
+ <option name="test-tag" value="FrameworksAppFunctionsTests" />
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.frameworks.appfunctionstests" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/services/tests/appfunctions/src/android/app/appfunctions/AppFunctionStaticMetadataHelperTest.kt b/services/tests/appfunctions/src/android/app/appfunctions/AppFunctionStaticMetadataHelperTest.kt
new file mode 100644
index 0000000..d8ce393
--- /dev/null
+++ b/services/tests/appfunctions/src/android/app/appfunctions/AppFunctionStaticMetadataHelperTest.kt
@@ -0,0 +1,57 @@
+/*
+ * 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.app.appfunctions
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class AppFunctionStaticMetadataHelperTest {
+
+ @Test
+ fun getStaticSchemaNameForPackage() {
+ val actualSchemaName =
+ AppFunctionStaticMetadataHelper.getStaticSchemaNameForPackage("com.example.app")
+
+ assertThat(actualSchemaName).isEqualTo("AppFunctionStaticMetadata-com.example.app")
+ }
+
+ @Test
+ fun getDocumentIdForAppFunction() {
+ val packageName = "com.example.app"
+ val functionId = "someFunction"
+
+ val actualDocumentId =
+ AppFunctionStaticMetadataHelper.getDocumentIdForAppFunction(packageName, functionId)
+
+ assertThat(actualDocumentId).isEqualTo("com.example.app/someFunction")
+ }
+
+ @Test
+ fun getStaticMetadataQualifiedId() {
+ val packageName = "com.example.app"
+ val functionId = "someFunction"
+
+ val actualQualifiedId =
+ AppFunctionStaticMetadataHelper.getStaticMetadataQualifiedId(packageName, functionId)
+
+ assertThat(actualQualifiedId)
+ .isEqualTo("android\$apps-db/app_functions#com.example.app/someFunction")
+ }
+}
diff --git a/services/tests/appfunctions/src/com/android/server/appfunctions/FutureAppSearchSessionTest.kt b/services/tests/appfunctions/src/com/android/server/appfunctions/FutureAppSearchSessionTest.kt
new file mode 100644
index 0000000..a0f1a55
--- /dev/null
+++ b/services/tests/appfunctions/src/com/android/server/appfunctions/FutureAppSearchSessionTest.kt
@@ -0,0 +1,164 @@
+/*
+ * 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.server.appfunctions
+
+import android.app.appfunctions.AppFunctionRuntimeMetadata
+import android.app.appfunctions.AppFunctionRuntimeMetadata.APP_FUNCTION_RUNTIME_NAMESPACE
+import android.app.appfunctions.AppFunctionRuntimeMetadata.createAppFunctionRuntimeSchema
+import android.app.appfunctions.AppFunctionRuntimeMetadata.createParentAppFunctionRuntimeSchema
+import android.app.appsearch.AppSearchManager
+import android.app.appsearch.PutDocumentsRequest
+import android.app.appsearch.SearchSpec
+import android.app.appsearch.SetSchemaRequest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.MoreExecutors
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class FutureAppSearchSessionTest {
+ private val context = InstrumentationRegistry.getInstrumentation().targetContext
+ private val appSearchManager = context.getSystemService(AppSearchManager::class.java)
+ private val testExecutor = MoreExecutors.directExecutor()
+
+ @Before
+ @After
+ fun clearData() {
+ val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build()
+ FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use {
+ val setSchemaRequest = SetSchemaRequest.Builder().setForceOverride(true).build()
+ it.setSchema(setSchemaRequest)
+ }
+ }
+
+ @Test
+ fun setSchema() {
+ val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build()
+ FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use { session ->
+ val setSchemaRequest =
+ SetSchemaRequest.Builder()
+ .addSchemas(
+ createParentAppFunctionRuntimeSchema(),
+ createAppFunctionRuntimeSchema(TEST_PACKAGE_NAME)
+ )
+ .build()
+
+ val schema = session.setSchema(setSchemaRequest)
+
+ assertThat(schema.get()).isNotNull()
+ }
+ }
+
+ @Test
+ fun put() {
+ val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build()
+ FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use { session ->
+ val setSchemaRequest =
+ SetSchemaRequest.Builder()
+ .addSchemas(
+ createParentAppFunctionRuntimeSchema(),
+ createAppFunctionRuntimeSchema(TEST_PACKAGE_NAME)
+ )
+ .build()
+ val schema = session.setSchema(setSchemaRequest)
+ assertThat(schema.get()).isNotNull()
+ val appFunctionRuntimeMetadata =
+ AppFunctionRuntimeMetadata.Builder(TEST_PACKAGE_NAME, TEST_FUNCTION_ID, "").build()
+ val putDocumentsRequest: PutDocumentsRequest =
+ PutDocumentsRequest.Builder()
+ .addGenericDocuments(appFunctionRuntimeMetadata)
+ .build()
+
+ val putResult = session.put(putDocumentsRequest)
+
+ assertThat(putResult.get().isSuccess).isTrue()
+ }
+ }
+
+ @Test
+ fun search() {
+ val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build()
+ FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use { session ->
+ val setSchemaRequest =
+ SetSchemaRequest.Builder()
+ .addSchemas(
+ createParentAppFunctionRuntimeSchema(),
+ createAppFunctionRuntimeSchema(TEST_PACKAGE_NAME)
+ )
+ .build()
+ val schema = session.setSchema(setSchemaRequest)
+ assertThat(schema.get()).isNotNull()
+ val appFunctionRuntimeMetadata =
+ AppFunctionRuntimeMetadata.Builder(TEST_PACKAGE_NAME, TEST_FUNCTION_ID, "").build()
+ val putDocumentsRequest: PutDocumentsRequest =
+ PutDocumentsRequest.Builder()
+ .addGenericDocuments(appFunctionRuntimeMetadata)
+ .build()
+ val putResult = session.put(putDocumentsRequest)
+ assertThat(putResult.get().isSuccess).isTrue()
+
+ val searchResult = session.search("", SearchSpec.Builder().build())
+
+ val genericDocs =
+ searchResult.get().nextPage.get().stream().map { it.genericDocument }.toList()
+ assertThat(genericDocs).hasSize(1)
+ val foundAppFunctionRuntimeMetadata = AppFunctionRuntimeMetadata(genericDocs[0])
+ assertThat(foundAppFunctionRuntimeMetadata.functionId).isEqualTo(TEST_FUNCTION_ID)
+ }
+ }
+
+ @Test
+ fun getByDocumentId() {
+ val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build()
+ FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use { session ->
+ val setSchemaRequest =
+ SetSchemaRequest.Builder()
+ .addSchemas(
+ createParentAppFunctionRuntimeSchema(),
+ createAppFunctionRuntimeSchema(TEST_PACKAGE_NAME)
+ )
+ .build()
+ val schema = session.setSchema(setSchemaRequest)
+ val appFunctionRuntimeMetadata =
+ AppFunctionRuntimeMetadata.Builder(TEST_PACKAGE_NAME, TEST_FUNCTION_ID, "").build()
+ val putDocumentsRequest: PutDocumentsRequest =
+ PutDocumentsRequest.Builder()
+ .addGenericDocuments(appFunctionRuntimeMetadata)
+ .build()
+ val putResult = session.put(putDocumentsRequest)
+
+ val genricDocument = session
+ .getByDocumentId(
+ /* documentId= */ "${TEST_PACKAGE_NAME}/${TEST_FUNCTION_ID}",
+ APP_FUNCTION_RUNTIME_NAMESPACE
+ )
+ .get()
+
+ val foundAppFunctionRuntimeMetadata = AppFunctionRuntimeMetadata(genricDocument)
+ assertThat(foundAppFunctionRuntimeMetadata.functionId).isEqualTo(TEST_FUNCTION_ID)
+ }
+ }
+
+ private companion object {
+ const val TEST_DB: String = "test_db"
+ const val TEST_PACKAGE_NAME: String = "test_pkg"
+ const val TEST_FUNCTION_ID: String = "print"
+ }
+}
diff --git a/services/tests/appfunctions/src/com/android/server/appfunctions/FutureGlobalSearchSessionTest.kt b/services/tests/appfunctions/src/com/android/server/appfunctions/FutureGlobalSearchSessionTest.kt
new file mode 100644
index 0000000..1fa55c7
--- /dev/null
+++ b/services/tests/appfunctions/src/com/android/server/appfunctions/FutureGlobalSearchSessionTest.kt
@@ -0,0 +1,125 @@
+/*
+ * 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.server.appfunctions
+
+import android.app.appfunctions.AppFunctionRuntimeMetadata
+import android.app.appfunctions.AppFunctionRuntimeMetadata.createAppFunctionRuntimeSchema
+import android.app.appfunctions.AppFunctionRuntimeMetadata.createParentAppFunctionRuntimeSchema
+import android.app.appsearch.AppSearchManager
+import android.app.appsearch.AppSearchManager.SearchContext
+import android.app.appsearch.PutDocumentsRequest
+import android.app.appsearch.SetSchemaRequest
+import android.app.appsearch.observer.DocumentChangeInfo
+import android.app.appsearch.observer.ObserverCallback
+import android.app.appsearch.observer.ObserverSpec
+import android.app.appsearch.observer.SchemaChangeInfo
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.internal.infra.AndroidFuture
+import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.MoreExecutors
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class FutureGlobalSearchSessionTest {
+ private val context = InstrumentationRegistry.getInstrumentation().targetContext
+ private val appSearchManager = context.getSystemService(AppSearchManager::class.java)
+ private val testExecutor = MoreExecutors.directExecutor()
+
+ @Before
+ @After
+ fun clearData() {
+ val searchContext = SearchContext.Builder(TEST_DB).build()
+ FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use {
+ val setSchemaRequest = SetSchemaRequest.Builder().setForceOverride(true).build()
+ it.setSchema(setSchemaRequest)
+ }
+ }
+
+ @Test
+ fun registerDocumentChangeObserverCallback() {
+ val packageObserverSpec: ObserverSpec =
+ ObserverSpec.Builder()
+ .addFilterSchemas(
+ AppFunctionRuntimeMetadata.getRuntimeSchemaNameForPackage(TEST_TARGET_PKG_NAME)
+ )
+ .build()
+ val settableDocumentChangeInfo: AndroidFuture<DocumentChangeInfo> = AndroidFuture()
+ val observer: ObserverCallback =
+ object : ObserverCallback {
+ override fun onSchemaChanged(changeInfo: SchemaChangeInfo) {}
+
+ override fun onDocumentChanged(changeInfo: DocumentChangeInfo) {
+ settableDocumentChangeInfo.complete(changeInfo)
+ }
+ }
+ val futureGlobalSearchSession = FutureGlobalSearchSession(appSearchManager, testExecutor)
+
+ val registerPackageObserver: Void? =
+ futureGlobalSearchSession
+ .registerObserverCallbackAsync(
+ TEST_TARGET_PKG_NAME,
+ packageObserverSpec,
+ testExecutor,
+ observer,
+ )
+ .get()
+ assertThat(registerPackageObserver).isNull()
+ // Trigger document change
+ val searchContext = SearchContext.Builder(TEST_DB).build()
+ FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use { session ->
+ val setSchemaRequest =
+ SetSchemaRequest.Builder()
+ .addSchemas(
+ createParentAppFunctionRuntimeSchema(),
+ createAppFunctionRuntimeSchema(TEST_TARGET_PKG_NAME),
+ )
+ .build()
+ val schema = session.setSchema(setSchemaRequest)
+ assertThat(schema.get()).isNotNull()
+ val appFunctionRuntimeMetadata =
+ AppFunctionRuntimeMetadata.Builder(TEST_TARGET_PKG_NAME, TEST_FUNCTION_ID, "")
+ .build()
+ val putDocumentsRequest: PutDocumentsRequest =
+ PutDocumentsRequest.Builder()
+ .addGenericDocuments(appFunctionRuntimeMetadata)
+ .build()
+ val putResult = session.put(putDocumentsRequest).get()
+ assertThat(putResult.isSuccess).isTrue()
+ }
+ assertThat(
+ settableDocumentChangeInfo
+ .get()
+ .changedDocumentIds
+ .contains(
+ AppFunctionRuntimeMetadata.getDocumentIdForAppFunction(
+ TEST_TARGET_PKG_NAME,
+ TEST_FUNCTION_ID,
+ )
+ )
+ )
+ .isTrue()
+ }
+
+ private companion object {
+ const val TEST_DB: String = "test_db"
+ const val TEST_TARGET_PKG_NAME = "com.android.frameworks.appfunctionstests"
+ const val TEST_FUNCTION_ID: String = "print"
+ }
+}
diff --git a/services/tests/appfunctions/src/com/android/server/appfunctions/MetadataSyncAdapterTest.kt b/services/tests/appfunctions/src/com/android/server/appfunctions/MetadataSyncAdapterTest.kt
new file mode 100644
index 0000000..1061da2
--- /dev/null
+++ b/services/tests/appfunctions/src/com/android/server/appfunctions/MetadataSyncAdapterTest.kt
@@ -0,0 +1,296 @@
+/*
+ * 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.server.appfunctions
+
+import android.app.appfunctions.AppFunctionRuntimeMetadata
+import android.app.appfunctions.AppFunctionRuntimeMetadata.PROPERTY_FUNCTION_ID
+import android.app.appfunctions.AppFunctionRuntimeMetadata.PROPERTY_PACKAGE_NAME
+import android.app.appsearch.AppSearchManager
+import android.app.appsearch.AppSearchManager.SearchContext
+import android.app.appsearch.PutDocumentsRequest
+import android.app.appsearch.SearchSpec
+import android.app.appsearch.SetSchemaRequest
+import android.util.ArrayMap
+import android.util.ArraySet
+import androidx.test.platform.app.InstrumentationRegistry
+import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.MoreExecutors
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class MetadataSyncAdapterTest {
+ private val context = InstrumentationRegistry.getInstrumentation().targetContext
+ private val appSearchManager = context.getSystemService(AppSearchManager::class.java)
+ private val testExecutor = MoreExecutors.directExecutor()
+
+ @Before
+ @After
+ fun clearData() {
+ val searchContext = SearchContext.Builder(TEST_DB).build()
+ FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use {
+ val setSchemaRequest = SetSchemaRequest.Builder().setForceOverride(true).build()
+ it.setSchema(setSchemaRequest)
+ }
+ }
+
+ @Test
+ fun getPackageToFunctionIdMap() {
+ val searchContext: SearchContext = SearchContext.Builder(TEST_DB).build()
+ val functionRuntimeMetadata =
+ AppFunctionRuntimeMetadata.Builder(TEST_TARGET_PKG_NAME, "testFunctionId", "").build()
+ val setSchemaRequest =
+ SetSchemaRequest.Builder()
+ .addSchemas(AppFunctionRuntimeMetadata.createParentAppFunctionRuntimeSchema())
+ .addSchemas(
+ AppFunctionRuntimeMetadata.createAppFunctionRuntimeSchema(TEST_TARGET_PKG_NAME)
+ )
+ .build()
+ val putDocumentsRequest: PutDocumentsRequest =
+ PutDocumentsRequest.Builder().addGenericDocuments(functionRuntimeMetadata).build()
+ FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use {
+ val setSchemaResponse = it.setSchema(setSchemaRequest).get()
+ assertThat(setSchemaResponse).isNotNull()
+ val appSearchBatchResult = it.put(putDocumentsRequest).get()
+ assertThat(appSearchBatchResult.isSuccess).isTrue()
+ }
+
+ val metadataSyncAdapter =
+ MetadataSyncAdapter(
+ testExecutor,
+ FutureAppSearchSession(appSearchManager, testExecutor, searchContext),
+ )
+ val searchSpec: SearchSpec =
+ SearchSpec.Builder()
+ .addFilterSchemas(
+ AppFunctionRuntimeMetadata.RUNTIME_SCHEMA_TYPE,
+ AppFunctionRuntimeMetadata.createAppFunctionRuntimeSchema(TEST_TARGET_PKG_NAME)
+ .schemaType,
+ )
+ .build()
+ val packageToFunctionIdMap =
+ metadataSyncAdapter.getPackageToFunctionIdMap(
+ "",
+ searchSpec,
+ PROPERTY_FUNCTION_ID,
+ PROPERTY_PACKAGE_NAME,
+ )
+
+ assertThat(packageToFunctionIdMap).isNotNull()
+ assertThat(packageToFunctionIdMap[TEST_TARGET_PKG_NAME]).containsExactly("testFunctionId")
+ }
+
+ @Test
+ fun getPackageToFunctionIdMap_multipleDocuments() {
+ val searchContext: SearchContext = SearchContext.Builder(TEST_DB).build()
+ val functionRuntimeMetadata =
+ AppFunctionRuntimeMetadata.Builder(TEST_TARGET_PKG_NAME, "testFunctionId", "").build()
+ val functionRuntimeMetadata1 =
+ AppFunctionRuntimeMetadata.Builder(TEST_TARGET_PKG_NAME, "testFunctionId1", "").build()
+ val functionRuntimeMetadata2 =
+ AppFunctionRuntimeMetadata.Builder(TEST_TARGET_PKG_NAME, "testFunctionId2", "").build()
+ val functionRuntimeMetadata3 =
+ AppFunctionRuntimeMetadata.Builder(TEST_TARGET_PKG_NAME, "testFunctionId3", "").build()
+ val setSchemaRequest =
+ SetSchemaRequest.Builder()
+ .addSchemas(AppFunctionRuntimeMetadata.createParentAppFunctionRuntimeSchema())
+ .addSchemas(
+ AppFunctionRuntimeMetadata.createAppFunctionRuntimeSchema(TEST_TARGET_PKG_NAME)
+ )
+ .build()
+ val putDocumentsRequest: PutDocumentsRequest =
+ PutDocumentsRequest.Builder()
+ .addGenericDocuments(
+ functionRuntimeMetadata,
+ functionRuntimeMetadata1,
+ functionRuntimeMetadata2,
+ functionRuntimeMetadata3,
+ )
+ .build()
+ FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use {
+ val setSchemaResponse = it.setSchema(setSchemaRequest).get()
+ assertThat(setSchemaResponse).isNotNull()
+ val appSearchBatchResult = it.put(putDocumentsRequest).get()
+ assertThat(appSearchBatchResult.isSuccess).isTrue()
+ }
+
+ val metadataSyncAdapter =
+ MetadataSyncAdapter(
+ testExecutor,
+ FutureAppSearchSession(appSearchManager, testExecutor, searchContext),
+ )
+ val searchSpec: SearchSpec =
+ SearchSpec.Builder()
+ .setResultCountPerPage(1)
+ .addFilterSchemas(
+ AppFunctionRuntimeMetadata.RUNTIME_SCHEMA_TYPE,
+ AppFunctionRuntimeMetadata.createAppFunctionRuntimeSchema(TEST_TARGET_PKG_NAME)
+ .schemaType,
+ )
+ .build()
+ val packageToFunctionIdMap =
+ metadataSyncAdapter.getPackageToFunctionIdMap(
+ "",
+ searchSpec,
+ PROPERTY_FUNCTION_ID,
+ PROPERTY_PACKAGE_NAME,
+ )
+
+ assertThat(packageToFunctionIdMap).isNotNull()
+ assertThat(packageToFunctionIdMap[TEST_TARGET_PKG_NAME])
+ .containsExactly(
+ "testFunctionId",
+ "testFunctionId1",
+ "testFunctionId2",
+ "testFunctionId3",
+ )
+ }
+
+ @Test
+ fun getAddedFunctionsDiffMap_noDiff() {
+ val staticPackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+ staticPackageToFunctionMap.putAll(
+ mapOf(TEST_TARGET_PKG_NAME to ArraySet(setOf("testFunction1")))
+ )
+ val runtimePackageToFunctionMap: ArrayMap<String, ArraySet<String>> =
+ ArrayMap(staticPackageToFunctionMap)
+
+ val addedFunctionsDiffMap =
+ MetadataSyncAdapter.getAddedFunctionsDiffMap(
+ staticPackageToFunctionMap,
+ runtimePackageToFunctionMap,
+ )
+
+ assertThat(addedFunctionsDiffMap.isEmpty()).isEqualTo(true)
+ }
+
+ @Test
+ fun getAddedFunctionsDiffMap_addedFunction() {
+ val staticPackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+ staticPackageToFunctionMap.putAll(
+ mapOf(TEST_TARGET_PKG_NAME to ArraySet(setOf("testFunction1", "testFunction2")))
+ )
+ val runtimePackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+ runtimePackageToFunctionMap.putAll(
+ mapOf(TEST_TARGET_PKG_NAME to ArraySet(setOf("testFunction1")))
+ )
+
+ val addedFunctionsDiffMap =
+ MetadataSyncAdapter.getAddedFunctionsDiffMap(
+ staticPackageToFunctionMap,
+ runtimePackageToFunctionMap,
+ )
+
+ assertThat(addedFunctionsDiffMap.size).isEqualTo(1)
+ assertThat(addedFunctionsDiffMap[TEST_TARGET_PKG_NAME]).containsExactly("testFunction2")
+ }
+
+ @Test
+ fun getAddedFunctionsDiffMap_addedFunctionNewPackage() {
+ val staticPackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+ staticPackageToFunctionMap.putAll(
+ mapOf(TEST_TARGET_PKG_NAME to ArraySet(setOf("testFunction1")))
+ )
+ val runtimePackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+
+ val addedFunctionsDiffMap =
+ MetadataSyncAdapter.getAddedFunctionsDiffMap(
+ staticPackageToFunctionMap,
+ runtimePackageToFunctionMap,
+ )
+
+ assertThat(addedFunctionsDiffMap.size).isEqualTo(1)
+ assertThat(addedFunctionsDiffMap[TEST_TARGET_PKG_NAME]).containsExactly("testFunction1")
+ }
+
+ @Test
+ fun getAddedFunctionsDiffMap_removedFunction() {
+ val staticPackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+ val runtimePackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+ runtimePackageToFunctionMap.putAll(
+ mapOf(TEST_TARGET_PKG_NAME to ArraySet(setOf("testFunction1")))
+ )
+
+ val addedFunctionsDiffMap =
+ MetadataSyncAdapter.getAddedFunctionsDiffMap(
+ staticPackageToFunctionMap,
+ runtimePackageToFunctionMap,
+ )
+
+ assertThat(addedFunctionsDiffMap.isEmpty()).isEqualTo(true)
+ }
+
+ @Test
+ fun getRemovedFunctionsDiffMap_noDiff() {
+ val staticPackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+ staticPackageToFunctionMap.putAll(
+ mapOf(TEST_TARGET_PKG_NAME to ArraySet(setOf("testFunction1")))
+ )
+ val runtimePackageToFunctionMap: ArrayMap<String, ArraySet<String>> =
+ ArrayMap(staticPackageToFunctionMap)
+
+ val removedFunctionsDiffMap =
+ MetadataSyncAdapter.getRemovedFunctionsDiffMap(
+ staticPackageToFunctionMap,
+ runtimePackageToFunctionMap,
+ )
+
+ assertThat(removedFunctionsDiffMap.isEmpty()).isEqualTo(true)
+ }
+
+ @Test
+ fun getRemovedFunctionsDiffMap_removedFunction() {
+ val staticPackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+ val runtimePackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+ runtimePackageToFunctionMap.putAll(
+ mapOf(TEST_TARGET_PKG_NAME to ArraySet(setOf("testFunction1")))
+ )
+
+ val removedFunctionsDiffMap =
+ MetadataSyncAdapter.getRemovedFunctionsDiffMap(
+ staticPackageToFunctionMap,
+ runtimePackageToFunctionMap,
+ )
+
+ assertThat(removedFunctionsDiffMap.size).isEqualTo(1)
+ assertThat(removedFunctionsDiffMap[TEST_TARGET_PKG_NAME]).containsExactly("testFunction1")
+ }
+
+ @Test
+ fun getRemovedFunctionsDiffMap_addedFunction() {
+ val staticPackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+ staticPackageToFunctionMap.putAll(
+ mapOf(TEST_TARGET_PKG_NAME to ArraySet(setOf("testFunction1")))
+ )
+ val runtimePackageToFunctionMap: ArrayMap<String, ArraySet<String>> = ArrayMap()
+
+ val removedFunctionsDiffMap =
+ MetadataSyncAdapter.getRemovedFunctionsDiffMap(
+ staticPackageToFunctionMap,
+ runtimePackageToFunctionMap,
+ )
+
+ assertThat(removedFunctionsDiffMap.isEmpty()).isEqualTo(true)
+ }
+
+ private companion object {
+ const val TEST_DB: String = "test_db"
+ const val TEST_TARGET_PKG_NAME = "com.android.frameworks.appfunctionstests"
+ }
+}
diff --git a/services/tests/displayservicetests/Android.bp b/services/tests/displayservicetests/Android.bp
index 3bafe72..61350bf 100644
--- a/services/tests/displayservicetests/Android.bp
+++ b/services/tests/displayservicetests/Android.bp
@@ -56,3 +56,13 @@
enabled: false,
},
}
+
+test_module_config {
+ name: "DisplayServiceTests_server_display",
+ base: "DisplayServiceTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.display"],
+}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index 026fcc4..52f1cbd 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -64,6 +64,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManagerInternal;
import android.app.ActivityOptions.LaunchCookie;
import android.app.PropertyInvalidatedCache;
import android.companion.virtual.IVirtualDevice;
@@ -106,6 +107,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.MessageQueue;
+import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemProperties;
@@ -358,6 +360,7 @@
@Mock DisplayDeviceConfig mMockDisplayDeviceConfig;
@Mock PackageManagerInternal mMockPackageManagerInternal;
@Mock DisplayManagerInternal mMockDisplayManagerInternal;
+ @Mock ActivityManagerInternal mMockActivityManagerInternal;
@Mock DisplayAdapter mMockDisplayAdapter;
@Captor ArgumentCaptor<ContentRecordingSession> mContentRecordingSessionCaptor;
@@ -388,6 +391,8 @@
PackageManagerInternal.class, mMockPackageManagerInternal);
mLocalServiceKeeperRule.overrideLocalService(
DisplayManagerInternal.class, mMockDisplayManagerInternal);
+ mLocalServiceKeeperRule.overrideLocalService(
+ ActivityManagerInternal.class, mMockActivityManagerInternal);
Display display = mock(Display.class);
when(display.getDisplayAdjustments()).thenReturn(new DisplayAdjustments());
when(display.getBrightnessInfo()).thenReturn(mock(BrightnessInfo.class));
@@ -3049,6 +3054,74 @@
}
@Test
+ public void testBrightnessUpdates() {
+ DisplayManagerService displayManager =
+ new DisplayManagerService(mContext, mShortMockedInjector);
+ DisplayManagerInternal localService = displayManager.new LocalService();
+ DisplayManagerService.BinderService displayManagerBinderService =
+ displayManager.new BinderService();
+ registerDefaultDisplays(displayManager);
+ initDisplayPowerController(localService);
+
+ final float invalidBrightness = -0.3f;
+ final float brightnessOff = -1.0f;
+ final float minimumBrightness = 0.0f;
+ final float validBrightness = 0.5f;
+
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS_MODE,
+ Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
+
+ // set and check valid brightness
+ waitForIdleHandler(mPowerHandler);
+ displayManagerBinderService.setBrightness(Display.DEFAULT_DISPLAY, validBrightness);
+ waitForIdleHandler(mPowerHandler);
+ assertEquals(validBrightness,
+ displayManagerBinderService.getBrightness(Display.DEFAULT_DISPLAY),
+ FLOAT_TOLERANCE);
+
+ // set and check invalid brightness
+ waitForIdleHandler(mPowerHandler);
+ displayManagerBinderService.setBrightness(Display.DEFAULT_DISPLAY, invalidBrightness);
+ waitForIdleHandler(mPowerHandler);
+ assertEquals(PowerManager.BRIGHTNESS_MIN,
+ displayManagerBinderService.getBrightness(Display.DEFAULT_DISPLAY),
+ FLOAT_TOLERANCE);
+
+ // reset and check valid brightness
+ waitForIdleHandler(mPowerHandler);
+ displayManagerBinderService.setBrightness(Display.DEFAULT_DISPLAY, validBrightness);
+ waitForIdleHandler(mPowerHandler);
+ assertEquals(validBrightness,
+ displayManagerBinderService.getBrightness(Display.DEFAULT_DISPLAY),
+ FLOAT_TOLERANCE);
+
+ // set and check brightness off
+ waitForIdleHandler(mPowerHandler);
+ displayManagerBinderService.setBrightness(Display.DEFAULT_DISPLAY, brightnessOff);
+ waitForIdleHandler(mPowerHandler);
+ assertEquals(PowerManager.BRIGHTNESS_MIN,
+ displayManagerBinderService.getBrightness(Display.DEFAULT_DISPLAY),
+ FLOAT_TOLERANCE);
+
+ // reset and check valid brightness
+ waitForIdleHandler(mPowerHandler);
+ displayManagerBinderService.setBrightness(Display.DEFAULT_DISPLAY, validBrightness);
+ waitForIdleHandler(mPowerHandler);
+ assertEquals(validBrightness,
+ displayManagerBinderService.getBrightness(Display.DEFAULT_DISPLAY),
+ FLOAT_TOLERANCE);
+
+ // set and check minimum brightness
+ waitForIdleHandler(mPowerHandler);
+ displayManagerBinderService.setBrightness(Display.DEFAULT_DISPLAY, minimumBrightness);
+ waitForIdleHandler(mPowerHandler);
+ assertEquals(PowerManager.BRIGHTNESS_MIN,
+ displayManagerBinderService.getBrightness(Display.DEFAULT_DISPLAY),
+ FLOAT_TOLERANCE);
+ }
+
+ @Test
public void testResolutionChangeGetsBackedUp() throws Exception {
when(mMockFlags.isResolutionBackupRestoreEnabled()).thenReturn(true);
DisplayManagerService displayManager =
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayOffloadSessionImplTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayOffloadSessionImplTest.java
index 30c384a..5e868a3 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayOffloadSessionImplTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayOffloadSessionImplTest.java
@@ -38,7 +38,7 @@
private DisplayManagerInternal.DisplayOffloader mDisplayOffloader;
@Mock
- private DisplayPowerControllerInterface mDisplayPowerController;
+ private DisplayPowerController mDisplayPowerController;
private DisplayOffloadSessionImpl mSession;
diff --git a/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java
index a7e0ebd..120cc84 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -118,7 +118,7 @@
@Mock
private DisplayManagerFlags mFlags;
@Mock
- private DisplayPowerControllerInterface mMockedDisplayPowerController;
+ private DisplayPowerController mMockedDisplayPowerController;
private Handler mHandler;
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java
index f9dc122..da79f30 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessClamperControllerTest.java
@@ -226,7 +226,7 @@
float clampedBrightness = 0.6f;
float customAnimationRate = 0.01f;
when(mMockClamper.getBrightnessCap()).thenReturn(clampedBrightness);
- when(mMockClamper.getType()).thenReturn(BrightnessClamper.Type.THERMAL);
+ when(mMockClamper.getType()).thenReturn(BrightnessClamper.Type.POWER);
when(mMockClamper.getCustomAnimationRate()).thenReturn(customAnimationRate);
when(mMockClamper.isActive()).thenReturn(false);
mTestInjector.mCapturedChangeListener.onChanged();
@@ -250,7 +250,7 @@
float clampedBrightness = 0.6f;
float customAnimationRate = 0.01f;
when(mMockClamper.getBrightnessCap()).thenReturn(clampedBrightness);
- when(mMockClamper.getType()).thenReturn(BrightnessClamper.Type.THERMAL);
+ when(mMockClamper.getType()).thenReturn(BrightnessClamper.Type.POWER);
when(mMockClamper.getCustomAnimationRate()).thenReturn(customAnimationRate);
when(mMockClamper.isActive()).thenReturn(true);
mTestInjector.mCapturedChangeListener.onChanged();
@@ -274,7 +274,7 @@
float clampedBrightness = 0.8f;
float customAnimationRate = 0.01f;
when(mMockClamper.getBrightnessCap()).thenReturn(clampedBrightness);
- when(mMockClamper.getType()).thenReturn(BrightnessClamper.Type.THERMAL);
+ when(mMockClamper.getType()).thenReturn(BrightnessClamper.Type.POWER);
when(mMockClamper.getCustomAnimationRate()).thenReturn(customAnimationRate);
when(mMockClamper.isActive()).thenReturn(true);
mTestInjector.mCapturedChangeListener.onChanged();
@@ -298,7 +298,7 @@
float clampedBrightness = 0.6f;
float customAnimationRate = 0.01f;
when(mMockClamper.getBrightnessCap()).thenReturn(clampedBrightness);
- when(mMockClamper.getType()).thenReturn(BrightnessClamper.Type.THERMAL);
+ when(mMockClamper.getType()).thenReturn(BrightnessClamper.Type.POWER);
when(mMockClamper.getCustomAnimationRate()).thenReturn(customAnimationRate);
when(mMockClamper.isActive()).thenReturn(true);
mTestInjector.mCapturedChangeListener.onChanged();
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessThermalClamperTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessThermalClamperTest.java
deleted file mode 100644
index 9d16594..0000000
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessThermalClamperTest.java
+++ /dev/null
@@ -1,312 +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.server.display.brightness.clamper;
-
-import static com.android.server.display.config.DisplayDeviceConfigTestUtilsKt.createSensorData;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.verify;
-
-import android.hardware.display.DisplayManager;
-import android.os.IThermalEventListener;
-import android.os.IThermalService;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.Temperature;
-import android.provider.DeviceConfig;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.internal.annotations.Keep;
-import com.android.server.display.DisplayDeviceConfig;
-import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData;
-import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel;
-import com.android.server.display.config.SensorData;
-import com.android.server.display.feature.DeviceConfigParameterProvider;
-import com.android.server.testutils.FakeDeviceConfigInterface;
-import com.android.server.testutils.TestHandler;
-
-import junitparams.JUnitParamsRunner;
-import junitparams.Parameters;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.List;
-
-@RunWith(JUnitParamsRunner.class)
-public class BrightnessThermalClamperTest {
-
- private static final float FLOAT_TOLERANCE = 0.001f;
-
- private static final String DISPLAY_ID = "displayId";
- @Mock
- private IThermalService mMockThermalService;
- @Mock
- private BrightnessClamperController.ClamperChangeListener mMockClamperChangeListener;
-
- private final FakeDeviceConfigInterface mFakeDeviceConfigInterface =
- new FakeDeviceConfigInterface();
- private final TestHandler mTestHandler = new TestHandler(null);
- private BrightnessThermalClamper mClamper;
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mClamper = new BrightnessThermalClamper(new TestInjector(), mTestHandler,
- mMockClamperChangeListener, new TestThermalData());
- mTestHandler.flush();
- }
-
- @Test
- public void testTypeIsThermal() {
- assertEquals(BrightnessClamper.Type.THERMAL, mClamper.getType());
- }
-
- @Test
- public void testNoThrottlingData() {
- assertFalse(mClamper.isActive());
- assertEquals(PowerManager.BRIGHTNESS_MAX, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
- }
-
- @Keep
- private static Object[][] testThrottlingData() {
- // throttlingLevels, throttlingStatus, expectedActive, expectedBrightness
- return new Object[][] {
- // no throttling data
- {List.of(), Temperature.THROTTLING_LIGHT, false, PowerManager.BRIGHTNESS_MAX},
- // throttlingStatus < min throttling data
- {List.of(
- new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
- new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
- Temperature.THROTTLING_LIGHT, false, PowerManager.BRIGHTNESS_MAX},
- // throttlingStatus = min throttling data
- {List.of(
- new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
- new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
- Temperature.THROTTLING_MODERATE, true, 0.5f},
- // throttlingStatus between min and max throttling data
- {List.of(
- new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
- new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
- Temperature.THROTTLING_SEVERE, true, 0.5f},
- // throttlingStatus = max throttling data
- {List.of(
- new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
- new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
- Temperature.THROTTLING_CRITICAL, true, 0.1f},
- // throttlingStatus > max throttling data
- {List.of(
- new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
- new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
- Temperature.THROTTLING_EMERGENCY, true, 0.1f},
- };
- }
- @Test
- @Parameters(method = "testThrottlingData")
- public void testNotifyThrottlingAfterOnDisplayChange(List<ThrottlingLevel> throttlingLevels,
- @Temperature.ThrottlingStatus int throttlingStatus,
- boolean expectedActive, float expectedBrightness) throws RemoteException {
- IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
- mClamper.onDisplayChanged(new TestThermalData(throttlingLevels));
- mTestHandler.flush();
- assertFalse(mClamper.isActive());
- assertEquals(PowerManager.BRIGHTNESS_MAX, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
-
- thermalEventListener.notifyThrottling(createSkinTemperature(throttlingStatus));
- mTestHandler.flush();
- assertEquals(expectedActive, mClamper.isActive());
- assertEquals(expectedBrightness, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
- }
-
- @Test
- @Parameters(method = "testThrottlingData")
- public void testOnDisplayChangeAfterNotifyThrottling(List<ThrottlingLevel> throttlingLevels,
- @Temperature.ThrottlingStatus int throttlingStatus,
- boolean expectedActive, float expectedBrightness) throws RemoteException {
- IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
- thermalEventListener.notifyThrottling(createSkinTemperature(throttlingStatus));
- mTestHandler.flush();
- assertFalse(mClamper.isActive());
- assertEquals(PowerManager.BRIGHTNESS_MAX, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
-
- mClamper.onDisplayChanged(new TestThermalData(throttlingLevels));
- mTestHandler.flush();
- assertEquals(expectedActive, mClamper.isActive());
- assertEquals(expectedBrightness, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
- }
-
- @Test
- public void testOverrideData() throws RemoteException {
- IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
- thermalEventListener.notifyThrottling(createSkinTemperature(Temperature.THROTTLING_SEVERE));
- mTestHandler.flush();
- assertFalse(mClamper.isActive());
- assertEquals(PowerManager.BRIGHTNESS_MAX, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
-
- mClamper.onDisplayChanged(new TestThermalData(
- List.of(new ThrottlingLevel(PowerManager.THERMAL_STATUS_SEVERE, 0.5f))));
- mTestHandler.flush();
- assertTrue(mClamper.isActive());
- assertEquals(0.5f, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
-
- overrideThrottlingData("displayId,1,emergency,0.4");
- mClamper.onDeviceConfigChanged();
- mTestHandler.flush();
-
- assertFalse(mClamper.isActive());
- assertEquals(PowerManager.BRIGHTNESS_MAX, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
-
- overrideThrottlingData("displayId,1,moderate,0.4");
- mClamper.onDeviceConfigChanged();
- mTestHandler.flush();
-
- assertTrue(mClamper.isActive());
- assertEquals(0.4f, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
- }
-
- @Test
- public void testDisplaySensorBasedThrottling() throws RemoteException {
- final int severity = PowerManager.THERMAL_STATUS_SEVERE;
- IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
- // Update config to listen to display type sensor.
- final SensorData tempSensor = createSensorData("DISPLAY", "VIRTUAL-SKIN-DISPLAY");
- final TestThermalData thermalData =
- new TestThermalData(
- DISPLAY_ID,
- DisplayDeviceConfig.DEFAULT_ID,
- List.of(new ThrottlingLevel(severity, 0.5f)),
- tempSensor);
- mClamper.onDisplayChanged(thermalData);
- mTestHandler.flush();
- verify(mMockThermalService).unregisterThermalEventListener(thermalEventListener);
- thermalEventListener = captureThermalEventListener(Temperature.TYPE_DISPLAY);
- assertFalse(mClamper.isActive());
-
- // Verify no throttling triggered when any other sensor notification received.
- thermalEventListener.notifyThrottling(createSkinTemperature(severity));
- mTestHandler.flush();
- assertFalse(mClamper.isActive());
-
- thermalEventListener.notifyThrottling(createDisplayTemperature("OTHER-SENSOR", severity));
- mTestHandler.flush();
- assertFalse(mClamper.isActive());
-
- assertEquals(PowerManager.BRIGHTNESS_MAX, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
-
- // Verify throttling triggered when display sensor of given name throttled.
- thermalEventListener.notifyThrottling(createDisplayTemperature(tempSensor.name, severity));
- mTestHandler.flush();
- assertTrue(mClamper.isActive());
- assertEquals(0.5f, mClamper.getBrightnessCap(), FLOAT_TOLERANCE);
- }
-
- private IThermalEventListener captureSkinThermalEventListener() throws RemoteException {
- return captureThermalEventListener(Temperature.TYPE_SKIN);
- }
-
- private IThermalEventListener captureThermalEventListener(int type) throws RemoteException {
- ArgumentCaptor<IThermalEventListener> captor = ArgumentCaptor.forClass(
- IThermalEventListener.class);
- verify(mMockThermalService).registerThermalEventListenerWithType(captor.capture(), eq(
- type));
- return captor.getValue();
- }
-
- private Temperature createDisplayTemperature(
- @NonNull String sensorName, @Temperature.ThrottlingStatus int status) {
- return new Temperature(100, Temperature.TYPE_DISPLAY, sensorName, status);
- }
-
- private Temperature createSkinTemperature(@Temperature.ThrottlingStatus int status) {
- return new Temperature(100, Temperature.TYPE_SKIN, "test_temperature", status);
- }
-
- private void overrideThrottlingData(String data) {
- mFakeDeviceConfigInterface.putProperty(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
- DisplayManager.DeviceConfig.KEY_BRIGHTNESS_THROTTLING_DATA, data);
- }
-
- private class TestInjector extends BrightnessThermalClamper.Injector {
- @Override
- IThermalService getThermalService() {
- return mMockThermalService;
- }
-
- @Override
- DeviceConfigParameterProvider getDeviceConfigParameterProvider() {
- return new DeviceConfigParameterProvider(mFakeDeviceConfigInterface);
- }
- }
-
- private static class TestThermalData implements BrightnessThermalClamper.ThermalData {
-
- private final String mUniqueDisplayId;
- private final String mDataId;
- private final ThermalBrightnessThrottlingData mData;
- private final SensorData mTempSensor;
-
- private TestThermalData() {
- this(DISPLAY_ID, DisplayDeviceConfig.DEFAULT_ID, null,
- SensorData.loadTempSensorUnspecifiedConfig());
- }
-
- private TestThermalData(List<ThrottlingLevel> data) {
- this(DISPLAY_ID, DisplayDeviceConfig.DEFAULT_ID, data,
- SensorData.loadTempSensorUnspecifiedConfig());
- }
-
- private TestThermalData(String uniqueDisplayId, String dataId, List<ThrottlingLevel> data,
- SensorData tempSensor) {
- mUniqueDisplayId = uniqueDisplayId;
- mDataId = dataId;
- mData = ThermalBrightnessThrottlingData.create(data);
- mTempSensor = tempSensor;
- }
-
- @NonNull
- @Override
- public String getUniqueDisplayId() {
- return mUniqueDisplayId;
- }
-
- @NonNull
- @Override
- public String getThermalThrottlingDataId() {
- return mDataId;
- }
-
- @Nullable
- @Override
- public ThermalBrightnessThrottlingData getThermalBrightnessThrottlingData() {
- return mData;
- }
-
- @NonNull
- @Override
- public SensorData getTempSensor() {
- return mTempSensor;
- }
- }
-}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessThermalModifierTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessThermalModifierTest.java
new file mode 100644
index 0000000..35d384b
--- /dev/null
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/BrightnessThermalModifierTest.java
@@ -0,0 +1,378 @@
+/*
+ * 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.server.display.brightness.clamper;
+
+import static com.android.server.display.config.DisplayDeviceConfigTestUtilsKt.createSensorData;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.hardware.display.BrightnessInfo;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerInternal;
+import android.os.IBinder;
+import android.os.IThermalEventListener;
+import android.os.IThermalService;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.Temperature;
+import android.provider.DeviceConfig;
+
+import androidx.annotation.NonNull;
+
+import com.android.internal.annotations.Keep;
+import com.android.server.display.DisplayBrightnessState;
+import com.android.server.display.DisplayDeviceConfig;
+import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData;
+import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel;
+import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.clamper.BrightnessClamperController.ModifiersAggregatedState;
+import com.android.server.display.config.SensorData;
+import com.android.server.display.feature.DeviceConfigParameterProvider;
+import com.android.server.testutils.FakeDeviceConfigInterface;
+import com.android.server.testutils.TestHandler;
+
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@RunWith(JUnitParamsRunner.class)
+public class BrightnessThermalModifierTest {
+ private static final int NO_MODIFIER = 0;
+
+ private static final float FLOAT_TOLERANCE = 0.001f;
+
+ private static final String DISPLAY_ID = "displayId";
+ @Mock
+ private IThermalService mMockThermalService;
+ @Mock
+ private BrightnessClamperController.ClamperChangeListener mMockClamperChangeListener;
+ @Mock
+ private DisplayManagerInternal.DisplayPowerRequest mMockRequest;
+ @Mock
+ private DisplayDeviceConfig mMockDisplayDeviceConfig;
+ @Mock
+ private IBinder mMockBinder;
+
+ private final FakeDeviceConfigInterface mFakeDeviceConfigInterface =
+ new FakeDeviceConfigInterface();
+ private final TestHandler mTestHandler = new TestHandler(null);
+ private BrightnessThermalModifier mModifier;
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mMockDisplayDeviceConfig.getTempSensor())
+ .thenReturn(SensorData.loadTempSensorUnspecifiedConfig());
+ mModifier = new BrightnessThermalModifier(new TestInjector(), mTestHandler,
+ mMockClamperChangeListener,
+ ClamperTestUtilsKt.createDisplayDeviceData(mMockDisplayDeviceConfig, mMockBinder));
+ mTestHandler.flush();
+ }
+
+
+ @Test
+ public void testNoThrottlingData() {
+ assertModifierState(
+ 0.3f, true,
+ PowerManager.BRIGHTNESS_MAX, 0.3f,
+ false, true);
+ }
+
+ @Keep
+ private static Object[][] testThrottlingData() {
+ // throttlingLevels, throttlingStatus, expectedActive, expectedBrightness
+ return new Object[][] {
+ // no throttling data
+ {List.of(), Temperature.THROTTLING_LIGHT, false, PowerManager.BRIGHTNESS_MAX},
+ // throttlingStatus < min throttling data
+ {List.of(
+ new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
+ new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
+ Temperature.THROTTLING_LIGHT, false, PowerManager.BRIGHTNESS_MAX},
+ // throttlingStatus = min throttling data
+ {List.of(
+ new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
+ new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
+ Temperature.THROTTLING_MODERATE, true, 0.5f},
+ // throttlingStatus between min and max throttling data
+ {List.of(
+ new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
+ new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
+ Temperature.THROTTLING_SEVERE, true, 0.5f},
+ // throttlingStatus = max throttling data
+ {List.of(
+ new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
+ new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
+ Temperature.THROTTLING_CRITICAL, true, 0.1f},
+ // throttlingStatus > max throttling data
+ {List.of(
+ new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.5f),
+ new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.1f)),
+ Temperature.THROTTLING_EMERGENCY, true, 0.1f},
+ };
+ }
+ @Test
+ @Parameters(method = "testThrottlingData")
+ public void testNotifyThrottlingAfterOnDisplayChange(List<ThrottlingLevel> throttlingLevels,
+ @Temperature.ThrottlingStatus int throttlingStatus,
+ boolean expectedActive, float expectedBrightness) throws RemoteException {
+ IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
+ onDisplayChange(throttlingLevels);
+ mTestHandler.flush();
+ assertModifierState(
+ PowerManager.BRIGHTNESS_MAX, true,
+ PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_MAX,
+ false, true);
+
+ thermalEventListener.notifyThrottling(createSkinTemperature(throttlingStatus));
+ mTestHandler.flush();
+ assertModifierState(
+ PowerManager.BRIGHTNESS_MAX, true,
+ expectedBrightness, expectedBrightness,
+ expectedActive, !expectedActive);
+ }
+
+ @Test
+ @Parameters(method = "testThrottlingData")
+ public void testOnDisplayChangeAfterNotifyThrottling(List<ThrottlingLevel> throttlingLevels,
+ @Temperature.ThrottlingStatus int throttlingStatus,
+ boolean expectedActive, float expectedBrightness) throws RemoteException {
+ IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
+ thermalEventListener.notifyThrottling(createSkinTemperature(throttlingStatus));
+ mTestHandler.flush();
+
+ assertModifierState(
+ PowerManager.BRIGHTNESS_MAX, true,
+ PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_MAX,
+ false, true);
+
+ onDisplayChange(throttlingLevels);
+ mTestHandler.flush();
+ assertModifierState(
+ PowerManager.BRIGHTNESS_MAX, true,
+ expectedBrightness, expectedBrightness,
+ expectedActive, !expectedActive);
+ }
+
+ @Test
+ public void testAppliesFastChangeOnlyOnActivation() throws RemoteException {
+ IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
+ onDisplayChange(List.of(new ThrottlingLevel(PowerManager.THERMAL_STATUS_SEVERE, 0.5f)));
+ mTestHandler.flush();
+
+ thermalEventListener.notifyThrottling(createSkinTemperature(Temperature.THROTTLING_SEVERE));
+ mTestHandler.flush();
+
+ // expectedSlowChange = false
+ assertModifierState(
+ PowerManager.BRIGHTNESS_MAX, true,
+ 0.5f, 0.5f,
+ true, false);
+
+ // slowChange is unchanged
+ assertModifierState(
+ PowerManager.BRIGHTNESS_MAX, true,
+ 0.5f, 0.5f,
+ true, true);
+ }
+
+ @Test
+ public void testCapsMaxBrightnessOnly_currentBrightnessIsLowAndFastChange()
+ throws RemoteException {
+ IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
+ onDisplayChange(List.of(new ThrottlingLevel(PowerManager.THERMAL_STATUS_SEVERE, 0.5f)));
+ mTestHandler.flush();
+
+ thermalEventListener.notifyThrottling(createSkinTemperature(Temperature.THROTTLING_SEVERE));
+ mTestHandler.flush();
+
+ assertModifierState(
+ 0.1f, false,
+ 0.5f, 0.1f,
+ true, false);
+ }
+
+ @Test
+ public void testOverrideData() throws RemoteException {
+ IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
+ thermalEventListener.notifyThrottling(createSkinTemperature(Temperature.THROTTLING_SEVERE));
+ mTestHandler.flush();
+
+ assertModifierState(
+ PowerManager.BRIGHTNESS_MAX, true,
+ PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_MAX,
+ false, true);
+
+ onDisplayChange(List.of(new ThrottlingLevel(PowerManager.THERMAL_STATUS_SEVERE, 0.5f)));
+ mTestHandler.flush();
+
+ assertModifierState(
+ PowerManager.BRIGHTNESS_MAX, true,
+ 0.5f, 0.5f,
+ true, false);
+
+ overrideThrottlingData("displayId,1,emergency,0.4");
+ mModifier.onDeviceConfigChanged();
+ mTestHandler.flush();
+
+ assertModifierState(
+ PowerManager.BRIGHTNESS_MAX, true,
+ PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_MAX,
+ false, true);
+
+ overrideThrottlingData("displayId,1,moderate,0.4");
+ mModifier.onDeviceConfigChanged();
+ mTestHandler.flush();
+
+ assertModifierState(
+ PowerManager.BRIGHTNESS_MAX, true,
+ 0.4f, 0.4f,
+ true, false);
+ }
+
+ @Test
+ public void testDisplaySensorBasedThrottling() throws RemoteException {
+ final int severity = PowerManager.THERMAL_STATUS_SEVERE;
+ IThermalEventListener thermalEventListener = captureSkinThermalEventListener();
+ // Update config to listen to display type sensor.
+ SensorData tempSensor = createSensorData("DISPLAY", "VIRTUAL-SKIN-DISPLAY");
+
+ when(mMockDisplayDeviceConfig.getTempSensor()).thenReturn(tempSensor);
+ onDisplayChange(List.of(new ThrottlingLevel(severity, 0.5f)));
+ mTestHandler.flush();
+
+ verify(mMockThermalService).unregisterThermalEventListener(thermalEventListener);
+ thermalEventListener = captureThermalEventListener(Temperature.TYPE_DISPLAY);
+ assertModifierState(
+ PowerManager.BRIGHTNESS_MAX, true,
+ PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_MAX,
+ false, true);
+
+ // Verify no throttling triggered when any other sensor notification received.
+ thermalEventListener.notifyThrottling(createSkinTemperature(severity));
+ mTestHandler.flush();
+ assertModifierState(
+ PowerManager.BRIGHTNESS_MAX, true,
+ PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_MAX,
+ false, true);
+
+ thermalEventListener.notifyThrottling(createDisplayTemperature("OTHER-SENSOR", severity));
+ mTestHandler.flush();
+ assertModifierState(
+ PowerManager.BRIGHTNESS_MAX, true,
+ PowerManager.BRIGHTNESS_MAX, PowerManager.BRIGHTNESS_MAX,
+ false, true);
+
+ // Verify throttling triggered when display sensor of given name throttled.
+ thermalEventListener.notifyThrottling(createDisplayTemperature(tempSensor.name, severity));
+ mTestHandler.flush();
+ assertModifierState(
+ PowerManager.BRIGHTNESS_MAX, true,
+ 0.5f, 0.5f,
+ true, false);
+ }
+
+ private IThermalEventListener captureSkinThermalEventListener() throws RemoteException {
+ return captureThermalEventListener(Temperature.TYPE_SKIN);
+ }
+
+ private IThermalEventListener captureThermalEventListener(int type) throws RemoteException {
+ ArgumentCaptor<IThermalEventListener> captor = ArgumentCaptor.forClass(
+ IThermalEventListener.class);
+ verify(mMockThermalService).registerThermalEventListenerWithType(captor.capture(), eq(
+ type));
+ return captor.getValue();
+ }
+
+ private Temperature createDisplayTemperature(
+ @NonNull String sensorName, @Temperature.ThrottlingStatus int status) {
+ return new Temperature(100, Temperature.TYPE_DISPLAY, sensorName, status);
+ }
+
+ private Temperature createSkinTemperature(@Temperature.ThrottlingStatus int status) {
+ return new Temperature(100, Temperature.TYPE_SKIN, "test_temperature", status);
+ }
+
+ private void overrideThrottlingData(String data) {
+ mFakeDeviceConfigInterface.putProperty(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ DisplayManager.DeviceConfig.KEY_BRIGHTNESS_THROTTLING_DATA, data);
+ }
+
+ private void onDisplayChange(List<ThrottlingLevel> throttlingLevels) {
+ Map<String, ThermalBrightnessThrottlingData> throttlingLevelsMap = new HashMap<>();
+ throttlingLevelsMap.put(DisplayDeviceConfig.DEFAULT_ID,
+ ThermalBrightnessThrottlingData.create(throttlingLevels));
+ when(mMockDisplayDeviceConfig.getThermalBrightnessThrottlingDataMapByThrottlingId())
+ .thenReturn(throttlingLevelsMap);
+ mModifier.onDisplayChanged(ClamperTestUtilsKt.createDisplayDeviceData(
+ mMockDisplayDeviceConfig, mMockBinder, DISPLAY_ID, DisplayDeviceConfig.DEFAULT_ID));
+ }
+
+ private void assertModifierState(
+ float currentBrightness,
+ boolean currentSlowChange,
+ float maxBrightness, float brightness,
+ boolean isActive,
+ boolean isSlowChange) {
+ ModifiersAggregatedState modifierState = new ModifiersAggregatedState();
+ DisplayBrightnessState.Builder stateBuilder = DisplayBrightnessState.builder();
+ stateBuilder.setBrightness(currentBrightness);
+ stateBuilder.setIsSlowChange(currentSlowChange);
+
+ int maxBrightnessReason = isActive ? BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL
+ : BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE;
+ int modifier = isActive ? BrightnessReason.MODIFIER_THROTTLED : NO_MODIFIER;
+
+ mModifier.applyStateChange(modifierState);
+ assertThat(modifierState.mMaxBrightness).isEqualTo(maxBrightness);
+ assertThat(modifierState.mMaxBrightnessReason).isEqualTo(maxBrightnessReason);
+
+ mModifier.apply(mMockRequest, stateBuilder);
+
+ assertThat(stateBuilder.getMaxBrightness()).isWithin(FLOAT_TOLERANCE).of(maxBrightness);
+ assertThat(stateBuilder.getBrightness()).isWithin(FLOAT_TOLERANCE).of(brightness);
+ assertThat(stateBuilder.getBrightnessMaxReason()).isEqualTo(maxBrightnessReason);
+ assertThat(stateBuilder.getBrightnessReason().getModifier()).isEqualTo(modifier);
+ assertThat(stateBuilder.isSlowChange()).isEqualTo(isSlowChange);
+ }
+
+
+ private class TestInjector extends BrightnessThermalModifier.Injector {
+ @Override
+ IThermalService getThermalService() {
+ return mMockThermalService;
+ }
+
+ @Override
+ DeviceConfigParameterProvider getDeviceConfigParameterProvider() {
+ return new DeviceConfigParameterProvider(mFakeDeviceConfigInterface);
+ }
+ }
+}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/ClamperTestUtils.kt b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/ClamperTestUtils.kt
index 5fd848f..f21749e 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/ClamperTestUtils.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/ClamperTestUtils.kt
@@ -21,6 +21,7 @@
import com.android.server.display.DisplayDeviceConfig
import com.android.server.display.brightness.clamper.BrightnessClamperController.DisplayDeviceData
+@JvmOverloads
fun createDisplayDeviceData(
displayDeviceConfig: DisplayDeviceConfig,
displayToken: IBinder,
diff --git a/services/tests/dreamservicetests/Android.bp b/services/tests/dreamservicetests/Android.bp
index 6369d45..1f0e975 100644
--- a/services/tests/dreamservicetests/Android.bp
+++ b/services/tests/dreamservicetests/Android.bp
@@ -42,3 +42,13 @@
enabled: false,
},
}
+
+test_module_config {
+ name: "DreamServiceTests_server_dreams",
+ base: "DreamServiceTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.dreams"],
+}
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 9808d54..5a76931 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -333,3 +333,73 @@
test_suites: ["device-tests"],
include_filters: ["com.android.server.utils"],
}
+
+test_module_config {
+ name: "FrameworksMockingServicesTests_android_server",
+ base: "FrameworksMockingServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server"],
+}
+
+test_module_config {
+ name: "FrameworksMockingServicesTests_server_job",
+ base: "FrameworksMockingServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.job"],
+}
+
+test_module_config {
+ name: "FrameworksMockingServicesTests_server_tare",
+ base: "FrameworksMockingServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.tare"],
+}
+
+test_module_config {
+ name: "FrameworksMockingServicesTests_server_backup",
+ base: "FrameworksMockingServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.backup"],
+}
+
+test_module_config {
+ name: "FrameworksMockingServicesTests_server_rescuepartytest",
+ base: "FrameworksMockingServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.RescuePartyTest"],
+}
+
+test_module_config {
+ name: "FrameworksMockingServicesTests_server_power",
+ base: "FrameworksMockingServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.power"],
+}
+
+test_module_config {
+ name: "FrameworksMockingServicesTests_server_trust",
+ base: "FrameworksMockingServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.trust"],
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 51aa528..d957355 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -52,6 +52,7 @@
import static com.android.server.am.ProcessList.FOREGROUND_APP_ADJ;
import static com.android.server.am.ProcessList.HEAVY_WEIGHT_APP_ADJ;
import static com.android.server.am.ProcessList.HOME_APP_ADJ;
+import static com.android.server.am.ProcessList.INVALID_ADJ;
import static com.android.server.am.ProcessList.PERCEPTIBLE_APP_ADJ;
import static com.android.server.am.ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
import static com.android.server.am.ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ;
@@ -90,7 +91,6 @@
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.ApplicationExitInfo;
-import android.app.IApplicationThread;
import android.app.IServiceConnection;
import android.content.ComponentName;
import android.content.Context;
@@ -107,6 +107,7 @@
import android.platform.test.flag.junit.SetFlagsRule;
import android.util.ArrayMap;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import com.android.server.LocalServices;
import com.android.server.wm.ActivityServiceConnectionsHolder;
@@ -164,6 +165,10 @@
private static int sFirstCachedAdj = ProcessList.CACHED_APP_MIN_ADJ
+ ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
+ private static int sFirstUiCachedAdj = ProcessList.CACHED_APP_MIN_ADJ + 10;
+ private static int sFirstNonUiCachedAdj = ProcessList.CACHED_APP_MIN_ADJ + 20;
+ private static int sUiTierSize = 5;
+
private Context mContext;
private PackageManagerInternal mPackageManagerInternal;
private ActivityManagerService mService;
@@ -232,9 +237,6 @@
mInjector);
mService.mOomAdjuster.mAdjSeq = 10000;
mService.mWakefulness = new AtomicInteger(PowerManagerInternal.WAKEFULNESS_AWAKE);
- if (mService.mConstants.USE_TIERED_CACHED_ADJ) {
- sFirstCachedAdj = ProcessList.CACHED_APP_MIN_ADJ + 10;
- }
mSetFlagsRule.enableFlags(Flags.FLAG_NEW_FGS_RESTRICTION_LOGIC);
}
@@ -244,6 +246,7 @@
mService.mOomAdjuster.resetInternal();
mService.mOomAdjuster.mActiveUids.clear();
LocalServices.removeServiceForTest(PackageManagerInternal.class);
+ mInjector.reset();
}
private static <T> void setFieldValue(Class clazz, Object obj, String fieldName, T val) {
@@ -473,7 +476,8 @@
mService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
updateOomAdj(app);
- final int expectedAdj = sFirstCachedAdj;
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstUiCachedAdj : sFirstCachedAdj;
assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj,
SCHED_GROUP_BACKGROUND);
}
@@ -701,7 +705,9 @@
mInjector.jumpUptimeAheadTo(followUpTimeCaptor.getValue());
mService.mOomAdjuster.updateOomAdjFollowUpTargetsLocked();
- assertEquals(sFirstCachedAdj, app.mState.getSetAdj());
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstUiCachedAdj : sFirstCachedAdj;
+ assertEquals(expectedAdj, app.mState.getSetAdj());
// Follow up should not have been called again.
verify(mService.mHandler).sendEmptyMessageAtTime(eq(FOLLOW_UP_OOMADJUSTER_UPDATE_MSG),
followUpTimeCaptor.capture());
@@ -836,7 +842,9 @@
mInjector.jumpUptimeAheadTo(followUpTimeCaptor.getValue());
mService.mOomAdjuster.updateOomAdjFollowUpTargetsLocked();
- assertProcStates(app, PROCESS_STATE_LAST_ACTIVITY, CACHED_APP_MIN_ADJ,
+ int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstUiCachedAdj : CACHED_APP_MIN_ADJ;
+ assertProcStates(app, PROCESS_STATE_LAST_ACTIVITY, expectedAdj,
SCHED_GROUP_BACKGROUND, "previous-expired");
// Follow up should not have been called again.
verify(mService.mHandler).sendEmptyMessageAtTime(eq(FOLLOW_UP_OOMADJUSTER_UPDATE_MSG),
@@ -877,9 +885,15 @@
for (int i = 0; i < numberOfApps; i++) {
final int mruIndex = numberOfApps - i - 1;
- int expectedAdj = CACHED_APP_MIN_ADJ + (mruIndex * 2 * CACHED_APP_IMPORTANCE_LEVELS);
- if (expectedAdj > CACHED_APP_MAX_ADJ) {
- expectedAdj = CACHED_APP_MAX_ADJ;
+ int expectedAdj;
+ if (mService.mConstants.USE_TIERED_CACHED_ADJ) {
+ expectedAdj = (i < numberOfApps - sUiTierSize)
+ ? sFirstNonUiCachedAdj : sFirstUiCachedAdj + mruIndex;
+ } else {
+ expectedAdj = CACHED_APP_MIN_ADJ + (mruIndex * 2 * CACHED_APP_IMPORTANCE_LEVELS);
+ if (expectedAdj > CACHED_APP_MAX_ADJ) {
+ expectedAdj = CACHED_APP_MAX_ADJ;
+ }
}
assertProcStates(apps[i], PROCESS_STATE_LAST_ACTIVITY, expectedAdj,
SCHED_GROUP_BACKGROUND, "previous-expired");
@@ -1003,7 +1017,9 @@
updateOomAdj(client, app);
doReturn(null).when(mService).getTopApp();
- assertProcStates(app, PROCESS_STATE_SERVICE, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstUiCachedAdj : sFirstCachedAdj;
+ assertProcStates(app, PROCESS_STATE_SERVICE, expectedAdj, SCHED_GROUP_BACKGROUND);
}
@SuppressWarnings("GuardedBy")
@@ -1053,7 +1069,9 @@
mService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
updateOomAdj(app);
- assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND);
}
@SuppressWarnings("GuardedBy")
@@ -1469,7 +1487,9 @@
bindProvider(app, app, null, null, false);
updateOomAdj(app);
- assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND);
}
@SuppressWarnings("GuardedBy")
@@ -1484,7 +1504,9 @@
mService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
updateOomAdj(app, client);
- assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND);
}
@SuppressWarnings("GuardedBy")
@@ -1592,7 +1614,9 @@
mInjector.jumpUptimeAheadTo(followUpTimeCaptor.getValue());
mService.mOomAdjuster.updateOomAdjFollowUpTargetsLocked();
- assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND,
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND,
"cch-empty");
// Follow up should not have been called again.
verify(mService.mHandler).sendEmptyMessageAtTime(eq(FOLLOW_UP_OOMADJUSTER_UPDATE_MSG),
@@ -2623,12 +2647,11 @@
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
final int userOwner = 0;
final int userOther = 1;
- final int cachedAdj1 = mService.mConstants.USE_TIERED_CACHED_ADJ
- ? CACHED_APP_MIN_ADJ + 10
- : CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
- final int cachedAdj2 = mService.mConstants.USE_TIERED_CACHED_ADJ
- ? CACHED_APP_MIN_ADJ + 10
- : cachedAdj1 + ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
+
+ // cachedAdj1 and cachedAdj2 will be read if USE_TIERED_CACHED_ADJ is disabled. Otherwise,
+ // sFirstUiCachedAdj and sFirstNonUiCachedAdj are used instead.
+ final int cachedAdj1 = CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
+ final int cachedAdj2 = cachedAdj1 + ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
doReturn(userOwner).when(mService.mUserController).getCurrentUserId();
final ArrayList<ProcessRecord> lru = mService.mProcessList.getLruProcessesLOSP();
@@ -2669,8 +2692,12 @@
mService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
updateOomAdj();
- assertProcStates(app, true, PROCESS_STATE_SERVICE, cachedAdj1, "cch-started-ui-services");
- assertProcStates(app2, true, PROCESS_STATE_SERVICE, cachedAdj2, "cch-started-services");
+ assertProcStates(app, PROCESS_STATE_SERVICE,
+ mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstUiCachedAdj : cachedAdj1,
+ SCHED_GROUP_BACKGROUND, "cch-started-ui-services", true);
+ assertProcStates(app2, PROCESS_STATE_SERVICE,
+ mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj2,
+ SCHED_GROUP_BACKGROUND, "cch-started-services", true);
app.mState.setSetProcState(PROCESS_STATE_NONEXISTENT);
app.mState.setAdjType(null);
@@ -2678,7 +2705,8 @@
app.mState.setHasShownUi(false);
updateOomAdj();
- assertProcStates(app, false, PROCESS_STATE_SERVICE, SERVICE_ADJ, "started-services");
+ assertProcStates(app, PROCESS_STATE_SERVICE, SERVICE_ADJ, SCHED_GROUP_BACKGROUND,
+ "started-services", false);
app.mState.setSetProcState(PROCESS_STATE_NONEXISTENT);
app.mState.setAdjType(null);
@@ -2686,7 +2714,9 @@
s.lastActivity = now - mService.mConstants.MAX_SERVICE_INACTIVITY - 1;
updateOomAdj();
- assertProcStates(app, true, PROCESS_STATE_SERVICE, cachedAdj1, "cch-started-services");
+ assertProcStates(app, PROCESS_STATE_SERVICE,
+ mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj1,
+ SCHED_GROUP_BACKGROUND, "cch-started-services", true);
app.mServices.stopService(s);
app.mState.setSetProcState(PROCESS_STATE_NONEXISTENT);
@@ -2704,8 +2734,11 @@
app.mServices.startService(s);
updateOomAdj();
- assertProcStates(app, false, PROCESS_STATE_SERVICE, SERVICE_ADJ, "started-services");
- assertProcStates(app2, true, PROCESS_STATE_SERVICE, cachedAdj1, "cch-started-services");
+ assertProcStates(app, PROCESS_STATE_SERVICE, SERVICE_ADJ, SCHED_GROUP_BACKGROUND,
+ "started-services", false);
+ assertProcStates(app2, PROCESS_STATE_SERVICE,
+ mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj1,
+ SCHED_GROUP_BACKGROUND, "cch-started-services", true);
app.mState.setSetProcState(PROCESS_STATE_NONEXISTENT);
app.mState.setAdjType(null);
@@ -2714,15 +2747,21 @@
s.lastActivity = now - mService.mConstants.MAX_SERVICE_INACTIVITY - 1;
updateOomAdj();
- assertProcStates(app, false, PROCESS_STATE_SERVICE, SERVICE_ADJ, "started-services");
- assertProcStates(app2, true, PROCESS_STATE_SERVICE, cachedAdj1, "cch-started-services");
+ assertProcStates(app, PROCESS_STATE_SERVICE, SERVICE_ADJ, SCHED_GROUP_BACKGROUND,
+ "started-services", false);
+ assertProcStates(app2, PROCESS_STATE_SERVICE,
+ mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj1,
+ SCHED_GROUP_BACKGROUND, "cch-started-services", true);
doReturn(userOther).when(mService.mUserController).getCurrentUserId();
mService.mOomAdjuster.handleUserSwitchedLocked();
updateOomAdj();
- assertProcStates(app, true, PROCESS_STATE_SERVICE, cachedAdj1, "cch-started-services");
- assertProcStates(app2, false, PROCESS_STATE_SERVICE, SERVICE_ADJ, "started-services");
+ assertProcStates(app, PROCESS_STATE_SERVICE,
+ mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj1,
+ SCHED_GROUP_BACKGROUND, "cch-started-services", true);
+ assertProcStates(app2, PROCESS_STATE_SERVICE, SERVICE_ADJ, SCHED_GROUP_BACKGROUND,
+ "started-services", false);
}
@SuppressWarnings("GuardedBy")
@@ -2998,7 +3037,9 @@
mInjector.jumpUptimeAheadTo(followUpTimeCaptor.getValue());
mService.mOomAdjuster.updateOomAdjFollowUpTargetsLocked();
- assertProcStates(app, PROCESS_STATE_SERVICE, sFirstCachedAdj, SCHED_GROUP_BACKGROUND,
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+ assertProcStates(app, PROCESS_STATE_SERVICE, expectedAdj, SCHED_GROUP_BACKGROUND,
"cch-started-services");
// Follow up should not have been called again.
verify(mService.mHandler).sendEmptyMessageAtTime(eq(FOLLOW_UP_OOMADJUSTER_UPDATE_MSG),
@@ -3031,14 +3072,16 @@
mInjector.jumpUptimeAheadTo(followUpTimeCaptor.getValue());
mService.mOomAdjuster.updateOomAdjFollowUpTargetsLocked();
- assertProcStates(app1, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND,
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+ assertProcStates(app1, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND,
"cch-empty");
verify(mService.mHandler, atLeastOnce()).sendEmptyMessageAtTime(
eq(FOLLOW_UP_OOMADJUSTER_UPDATE_MSG), followUpTimeCaptor.capture());
mInjector.jumpUptimeAheadTo(followUpTimeCaptor.getValue());
mService.mOomAdjuster.updateOomAdjFollowUpTargetsLocked();
- assertProcStates(app2, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND,
+ assertProcStates(app2, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND,
"cch-empty");
}
@@ -3121,8 +3164,10 @@
private void assertProcStates(ProcessRecord app, int expectedProcState, int expectedAdj,
int expectedSchedGroup) {
final ProcessStateRecord state = app.mState;
+ final int pid = app.getPid();
assertEquals(expectedProcState, state.getSetProcState());
assertEquals(expectedAdj, state.getSetAdj());
+ assertEquals(expectedAdj, mInjector.mLastSetOomAdj.get(pid, INVALID_ADJ));
assertEquals(expectedSchedGroup, state.getSetSchedGroup());
// Below BFGS should never have BFSL.
@@ -3136,41 +3181,19 @@
}
@SuppressWarnings("GuardedBy")
- private void assertProcStates(ProcessRecord app, boolean expectedCached,
- int expectedProcState, int expectedAdj, String expectedAdjType) {
- final ProcessStateRecord state = app.mState;
- assertEquals(expectedCached, state.isCached());
- assertEquals(expectedProcState, state.getSetProcState());
- assertEquals(expectedAdj, state.getSetAdj());
- assertEquals(expectedAdjType, state.getAdjType());
-
- // Below BFGS should never have BFSL.
- if (expectedProcState > PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
- assertNoBfsl(app);
- }
- // Above FGS should always have BFSL.
- if (expectedProcState < PROCESS_STATE_FOREGROUND_SERVICE) {
- assertBfsl(app);
- }
- }
-
- @SuppressWarnings("GuardedBy")
private void assertProcStates(ProcessRecord app, int expectedProcState, int expectedAdj,
int expectedSchedGroup, String expectedAdjType) {
+ assertProcStates(app, expectedProcState, expectedAdj, expectedSchedGroup);
final ProcessStateRecord state = app.mState;
assertEquals(expectedAdjType, state.getAdjType());
- assertEquals(expectedProcState, state.getSetProcState());
- assertEquals(expectedAdj, state.getSetAdj());
- assertEquals(expectedSchedGroup, state.getSetSchedGroup());
+ }
- // Below BFGS should never have BFSL.
- if (expectedProcState > PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
- assertNoBfsl(app);
- }
- // Above FGS should always have BFSL.
- if (expectedProcState < PROCESS_STATE_FOREGROUND_SERVICE) {
- assertBfsl(app);
- }
+ @SuppressWarnings("GuardedBy")
+ private void assertProcStates(ProcessRecord app, int expectedProcState, int expectedAdj,
+ int expectedSchedGroup, String expectedAdjType, boolean expectedCached) {
+ assertProcStates(app, expectedProcState, expectedAdj, expectedSchedGroup, expectedAdjType);
+ final ProcessStateRecord state = app.mState;
+ assertEquals(expectedCached, state.isCached());
}
private class ProcessRecordBuilder {
@@ -3255,6 +3278,7 @@
eq(mSdkSandboxClientAppPackage), anyLong(), anyInt(), anyInt());
ProcessRecord app = new ProcessRecord(mService, ai, mProcessName, mUid,
mSdkSandboxClientAppPackage, -1, null);
+ app.setPid(mPid);
final ProcessStateRecord state = app.mState;
final ProcessServiceRecord services = app.mServices;
final ProcessReceiverRecord receivers = app.mReceivers;
@@ -3319,6 +3343,13 @@
static class OomAdjusterInjector extends OomAdjuster.Injector {
// Jump ahead in time by this offset amount.
long mTimeOffsetMillis = 0;
+ private SparseIntArray mLastSetOomAdj = new SparseIntArray();
+
+ void reset() {
+ mTimeOffsetMillis = 0;
+ mLastSetOomAdj.clear();
+ }
+
void jumpUptimeAheadTo(long uptimeMillis) {
final long jumpMs = uptimeMillis - getUptimeMillis();
@@ -3335,5 +3366,25 @@
long getElapsedRealtimeMillis() {
return SystemClock.elapsedRealtime() + mTimeOffsetMillis;
}
+
+ @Override
+ void batchSetOomAdj(ArrayList<ProcessRecord> procsToOomAdj) {
+ for (ProcessRecord proc : procsToOomAdj) {
+ final int pid = proc.getPid();
+ if (pid <= 0) continue;
+ mLastSetOomAdj.put(pid, proc.mState.getCurAdj());
+ }
+ }
+
+ @Override
+ void setOomAdj(int pid, int uid, int adj) {
+ if (pid <= 0) return;
+ mLastSetOomAdj.put(pid, adj);
+ }
+
+ @Override
+ void setThreadPriority(int tid, int priority) {
+ // do nothing
+ }
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobParametersTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobParametersTest.java
new file mode 100644
index 0000000..c8e4f89
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobParametersTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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.job;
+
+import static android.app.job.Flags.FLAG_CLEANUP_EMPTY_JOBS;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+
+import android.app.job.IJobCallback;
+import android.app.job.JobParameters;
+import android.net.Uri;
+import android.os.Parcel;
+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 org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+public class JobParametersTest {
+ private static final String TAG = JobParametersTest.class.getSimpleName();
+ private static final int TEST_JOB_ID_1 = 123;
+ private static final String TEST_NAMESPACE = "TEST_NAMESPACE";
+ private static final String TEST_DEBUG_STOP_REASON = "TEST_DEBUG_STOP_REASON";
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
+ private MockitoSession mMockingSession;
+ @Mock private Parcel mMockParcel;
+ @Mock private IJobCallback.Stub mMockJobCallbackStub;
+
+ @Before
+ public void setUp() throws Exception {
+ mMockingSession =
+ mockitoSession().initMocks(this).strictness(Strictness.LENIENT).startMocking();
+ }
+
+ @After
+ public void tearDown() {
+ if (mMockingSession != null) {
+ mMockingSession.finishMocking();
+ }
+
+ when(mMockParcel.readInt())
+ .thenReturn(TEST_JOB_ID_1) // Job ID
+ .thenReturn(0) // No clip data
+ .thenReturn(0) // No deadline expired
+ .thenReturn(0) // No network
+ .thenReturn(0) // No stop reason
+ .thenReturn(0); // Internal stop reason
+ when(mMockParcel.readString())
+ .thenReturn(TEST_NAMESPACE) // Job namespace
+ .thenReturn(TEST_DEBUG_STOP_REASON); // Debug stop reason
+ when(mMockParcel.readPersistableBundle()).thenReturn(null);
+ when(mMockParcel.readBundle()).thenReturn(null);
+ when(mMockParcel.readStrongBinder()).thenReturn(mMockJobCallbackStub);
+ when(mMockParcel.readBoolean())
+ .thenReturn(false) // expedited
+ .thenReturn(false); // user initiated
+ when(mMockParcel.createTypedArray(any())).thenReturn(new Uri[0]);
+ when(mMockParcel.createStringArray()).thenReturn(new String[0]);
+ }
+
+ /**
+ * Test to verify that the JobParameters created using Non-Parcelable constructor has not
+ * cleaner attached
+ */
+ @Test
+ public void testJobParametersNonParcelableConstructor_noCleaner() {
+ JobParameters jobParameters =
+ new JobParameters(
+ null,
+ TEST_NAMESPACE,
+ TEST_JOB_ID_1,
+ null,
+ null,
+ null,
+ 0,
+ false,
+ false,
+ false,
+ null,
+ null,
+ null);
+
+ // Verify that cleaner is not registered
+ assertThat(jobParameters.getCleanable()).isNull();
+ assertThat(jobParameters.getJobCleanupCallback()).isNull();
+ }
+
+ /**
+ * Test to verify that the JobParameters created using Parcelable constructor has not cleaner
+ * attached
+ */
+ @Test
+ public void testJobParametersParcelableConstructor_noCleaner() {
+ JobParameters jobParameters = JobParameters.CREATOR.createFromParcel(mMockParcel);
+
+ // Verify that cleaner is not registered
+ assertThat(jobParameters.getCleanable()).isNull();
+ assertThat(jobParameters.getJobCleanupCallback()).isNull();
+ }
+
+ /** Test to verify that the JobParameters Cleaner is disabled */
+ @RequiresFlagsEnabled(FLAG_CLEANUP_EMPTY_JOBS)
+ @Test
+ public void testCleanerWithLeakedJobCleanerDisabled_flagCleanupEmptyJobsEnabled() {
+ // Inject real JobCallbackCleanup
+ JobParameters jobParameters = JobParameters.CREATOR.createFromParcel(mMockParcel);
+
+ // Enable the cleaner
+ jobParameters.enableCleaner();
+
+ // Verify the cleaner is enabled
+ assertThat(jobParameters.getCleanable()).isNotNull();
+ assertThat(jobParameters.getJobCleanupCallback()).isNotNull();
+ assertThat(jobParameters.getJobCleanupCallback().isCleanerEnabled()).isTrue();
+
+ // Disable the cleaner
+ jobParameters.disableCleaner();
+
+ // Verify the cleaner is disabled
+ assertThat(jobParameters.getCleanable()).isNull();
+ assertThat(jobParameters.getJobCleanupCallback()).isNull();
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/rollback/Android.bp b/services/tests/mockingservicestests/src/com/android/server/rollback/Android.bp
index e94b8ad..6a16d1e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/rollback/Android.bp
+++ b/services/tests/mockingservicestests/src/com/android/server/rollback/Android.bp
@@ -54,3 +54,13 @@
"automotive-tests",
],
}
+
+test_module_config {
+ name: "RollbackPackageHealthObserverTests_server_rollback",
+ base: "RollbackPackageHealthObserverTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.rollback"],
+}
diff --git a/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java
index 7d04470..b2ca991 100644
--- a/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java
+++ b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java
@@ -631,7 +631,7 @@
CountDownLatch stopLatch2 = new CountDownLatch(1);
// negative value used for test only to avoid conflicting with any real thread that exists
int isoProc1 = -100;
- int isoProc2 = 9999;
+ int isoProc2 = 99999999;
when(mAmInternalMock.getIsolatedProcesses(eq(UID))).thenReturn(List.of(0));
int[] tids2 = createThreads(threadCount, stopLatch2);
int[] tids2WithIsolated = Arrays.copyOf(tids2, tids2.length + 2);
@@ -658,7 +658,7 @@
verify(mNativeWrapperMock, never()).halSetThreads(eq(sessionPtr1), any());
verify(mNativeWrapperMock, never()).halSetThreads(eq(sessionPtr2), any());
// the new TIDs pending list should be updated
- assertArrayEquals(session2.getTidsInternal(), expectedTids2);
+ assertArrayEquals(expectedTids2, session2.getTidsInternal());
reset(mNativeWrapperMock);
// this should resume and update the threads so those never-existed invalid isolated
@@ -713,8 +713,8 @@
// in background, set threads for session 1 then it should not be force paused next time
session1.setThreads(SESSION_TIDS_A);
// the new TIDs pending list should be updated
- assertArrayEquals(session1.getTidsInternal(), SESSION_TIDS_A);
- assertArrayEquals(session2.getTidsInternal(), expectedTids2);
+ assertArrayEquals(SESSION_TIDS_A, session1.getTidsInternal());
+ assertArrayEquals(expectedTids2, session2.getTidsInternal());
verifyAllHintsEnabled(session1, false);
verifyAllHintsEnabled(session2, false);
reset(mNativeWrapperMock);
diff --git a/services/tests/powerservicetests/Android.bp b/services/tests/powerservicetests/Android.bp
index 729dcbd..f8cc6d0 100644
--- a/services/tests/powerservicetests/Android.bp
+++ b/services/tests/powerservicetests/Android.bp
@@ -44,3 +44,13 @@
enabled: false,
},
}
+
+test_module_config {
+ name: "PowerServiceTests_server_power",
+ base: "PowerServiceTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.power"],
+}
diff --git a/services/tests/powerstatstests/Android.bp b/services/tests/powerstatstests/Android.bp
index b2a5b02..0e922ce 100644
--- a/services/tests/powerstatstests/Android.bp
+++ b/services/tests/powerstatstests/Android.bp
@@ -71,9 +71,31 @@
],
srcs: [
"src/com/android/server/power/stats/*.java",
+ "src/com/android/server/power/stats/format/*.java",
+ "src/com/android/server/power/stats/processor/*.java",
],
java_resources: [
"res/xml/power_profile*.xml",
],
auto_gen_config: true,
}
+
+test_module_config {
+ name: "PowerStatsTests_stats_bstatscputimesvalidationtest",
+ base: "PowerStatsTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.power.stats.BstatsCpuTimesValidationTest"],
+}
+
+test_module_config {
+ name: "PowerStatsTests_power_stats",
+ base: "PowerStatsTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.power.stats"],
+}
diff --git a/services/tests/powerstatstests/TEST_MAPPING b/services/tests/powerstatstests/TEST_MAPPING
index fb24361..1e8d2de 100644
--- a/services/tests/powerstatstests/TEST_MAPPING
+++ b/services/tests/powerstatstests/TEST_MAPPING
@@ -14,8 +14,7 @@
"name": "PowerStatsTestsRavenwood",
"host": true,
"options": [
- {"include-filter": "com.android.server.power.stats"},
- {"exclude-annotation": "android.platform.test.annotations.DisabledOnRavenwood"}
+ {"include-filter": "com.android.server.power.stats"}
]
}
],
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java
index a1101cd..1d20538 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java
@@ -117,7 +117,7 @@
private PowerStatsStore mPowerStatsStore;
private BatteryUsageStatsProvider mBatteryUsageStatsProvider;
@Mock
- private PowerStatsExporter mPowerStatsExporter;
+ private PowerAttributor mPowerAttributor;
@Before
public void setUp() throws IOException {
@@ -149,9 +149,8 @@
} else {
context = InstrumentationRegistry.getContext();
}
- mPowerStatsStore = new PowerStatsStore(systemDir, mHandler,
- new AggregatedPowerStatsConfig());
- mBatteryUsageStatsProvider = new BatteryUsageStatsProvider(context, mPowerStatsExporter,
+ mPowerStatsStore = new PowerStatsStore(systemDir, mHandler);
+ mBatteryUsageStatsProvider = new BatteryUsageStatsProvider(context, mPowerAttributor,
mPowerProfile, mBatteryStatsImpl.getCpuScalingPolicies(), mPowerStatsStore,
mMockClock);
}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
index 17c7efa..fde84e9 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
@@ -94,8 +94,9 @@
public void test_getBatteryUsageStats() {
BatteryStatsImpl batteryStats = prepareBatteryStats();
- BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext, null,
- mStatsRule.getPowerProfile(), mStatsRule.getCpuScalingPolicies(), null, mMockClock);
+ BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
+ mock(PowerAttributor.class), mStatsRule.getPowerProfile(),
+ mStatsRule.getCpuScalingPolicies(), mock(PowerStatsStore.class), mMockClock);
final BatteryUsageStats batteryUsageStats =
provider.getBatteryUsageStats(batteryStats, BatteryUsageStatsQuery.DEFAULT);
@@ -130,8 +131,9 @@
public void test_selectPowerComponents() {
BatteryStatsImpl batteryStats = prepareBatteryStats();
- BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext, null,
- mStatsRule.getPowerProfile(), mStatsRule.getCpuScalingPolicies(), null, mMockClock);
+ BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
+ mock(PowerAttributor.class), mStatsRule.getPowerProfile(),
+ mStatsRule.getCpuScalingPolicies(), mock(PowerStatsStore.class), mMockClock);
final BatteryUsageStats batteryUsageStats =
provider.getBatteryUsageStats(batteryStats,
@@ -235,8 +237,9 @@
batteryStats.noteAlarmFinishLocked("foo", null, APP_UID, 3_001_000, 2_001_000);
}
- BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext, null,
- mStatsRule.getPowerProfile(), mStatsRule.getCpuScalingPolicies(), null, mMockClock);
+ BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
+ mock(PowerAttributor.class), mStatsRule.getPowerProfile(),
+ mStatsRule.getCpuScalingPolicies(), mock(PowerStatsStore.class), mMockClock);
final BatteryUsageStats batteryUsageStats =
provider.getBatteryUsageStats(batteryStats,
@@ -323,8 +326,9 @@
}
}
- BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext, null,
- mStatsRule.getPowerProfile(), mStatsRule.getCpuScalingPolicies(), null, mMockClock);
+ BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
+ mock(PowerAttributor.class), mStatsRule.getPowerProfile(),
+ mStatsRule.getCpuScalingPolicies(), mock(PowerStatsStore.class), mMockClock);
final BatteryUsageStats batteryUsageStats =
provider.getBatteryUsageStats(batteryStats,
@@ -408,12 +412,12 @@
PowerStatsStore powerStatsStore = new PowerStatsStore(
new File(mStatsRule.getHistoryDir(), "powerstatsstore"),
- mStatsRule.getHandler(), null);
+ mStatsRule.getHandler());
powerStatsStore.reset();
- BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext, null,
- mStatsRule.getPowerProfile(), mStatsRule.getCpuScalingPolicies(), powerStatsStore,
- mMockClock);
+ BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
+ mock(PowerAttributor.class), mStatsRule.getPowerProfile(),
+ mStatsRule.getCpuScalingPolicies(), powerStatsStore, mMockClock);
batteryStats.saveBatteryUsageStatsOnReset(provider, powerStatsStore);
synchronized (batteryStats) {
@@ -522,8 +526,9 @@
batteryStats.updateCustomEnergyConsumerStatsLocked(1, 200_000_000, uidEnergies);
}
- BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext, null,
- mStatsRule.getPowerProfile(), mStatsRule.getCpuScalingPolicies(), null, mMockClock);
+ BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
+ mock(PowerAttributor.class), mStatsRule.getPowerProfile(),
+ mStatsRule.getCpuScalingPolicies(), mock(PowerStatsStore.class), mMockClock);
PowerStatsStore powerStatsStore = mock(PowerStatsStore.class);
doAnswer(invocation -> {
@@ -584,9 +589,9 @@
when(powerStatsStore.loadPowerStatsSpan(1, BatteryUsageStatsSection.TYPE))
.thenReturn(span1);
- BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext, null,
- mStatsRule.getPowerProfile(), mStatsRule.getCpuScalingPolicies(), powerStatsStore,
- mMockClock);
+ BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
+ mock(PowerAttributor.class), mStatsRule.getPowerProfile(),
+ mStatsRule.getCpuScalingPolicies(), powerStatsStore, mMockClock);
BatteryUsageStatsQuery query = new BatteryUsageStatsQuery.Builder()
.aggregateSnapshots(0, 3000)
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerStatsCollectorTest.java
index 02c7b74..e392c5d 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerStatsCollectorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerStatsCollectorTest.java
@@ -27,6 +27,7 @@
import android.bluetooth.UidTraffic;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerResult;
import android.hardware.power.stats.EnergyConsumerType;
import android.os.BatteryConsumer;
import android.os.Handler;
@@ -37,6 +38,7 @@
import com.android.internal.os.Clock;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.BluetoothPowerStatsLayout;
import org.junit.Before;
import org.junit.Rule;
@@ -48,7 +50,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
-import java.util.function.IntSupplier;
public class BluetoothPowerStatsCollectorTest {
private static final int APP_UID1 = 42;
@@ -132,11 +133,6 @@
}
@Override
- public IntSupplier getVoltageSupplier() {
- return () -> 3500;
- }
-
- @Override
public BluetoothPowerStatsCollector.BluetoothStatsRetriever
getBluetoothStatsRetriever() {
return mBluetoothStatsRetriever;
@@ -232,6 +228,7 @@
BluetoothPowerStatsCollector collector = new BluetoothPowerStatsCollector(mInjector);
collector.setEnabled(true);
+ when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(3500);
when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.BLUETOOTH))
.thenReturn(new int[]{777});
@@ -242,8 +239,7 @@
mUidScanTimes.put(APP_UID1, 100);
- when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{777})))
- .thenReturn(new long[]{10000});
+ mockConsumedEnergy(777, 10000);
// Establish a baseline
collector.collectStats();
@@ -258,13 +254,19 @@
mUidScanTimes.put(APP_UID2, 300);
mUidScanTimes.put(ISOLATED_UID, 400);
- when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{777})))
- .thenReturn(new long[]{64321});
+ mockConsumedEnergy(777, 64321);
mStatsRule.setTime(20000, 20000);
return collector.collectStats();
}
+ private void mockConsumedEnergy(int consumerId, long energyUWs) {
+ EnergyConsumerResult ecr = new EnergyConsumerResult();
+ ecr.energyUWs = energyUWs;
+ when(mConsumedEnergyRetriever.getConsumedEnergy(eq(new int[]{consumerId})))
+ .thenReturn(new EnergyConsumerResult[]{ecr});
+ }
+
private BluetoothActivityEnergyInfo mockBluetoothActivityEnergyInfo(long timestamp,
long rxTimeMs, long txTimeMs, long idleTimeMs, UidTraffic... uidTraffic) {
if (RavenwoodRule.isOnRavenwood()) {
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorTest.java
index d1105a4..1fea462 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsCollectorTest.java
@@ -26,6 +26,7 @@
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when;
+import android.hardware.power.stats.EnergyConsumerResult;
import android.hardware.power.stats.EnergyConsumerType;
import android.os.BatteryConsumer;
import android.os.ConditionVariable;
@@ -42,6 +43,7 @@
import com.android.internal.os.CpuScalingPolicies;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.CpuPowerStatsLayout;
import org.junit.Before;
import org.junit.Rule;
@@ -53,7 +55,6 @@
import java.io.IOException;
import java.io.StringWriter;
-import java.util.function.IntSupplier;
@RunWith(AndroidJUnit4.class)
@SmallTest
@@ -124,11 +125,6 @@
}
@Override
- public IntSupplier getVoltageSupplier() {
- return () -> 3500;
- }
-
- @Override
public long getPowerStatsCollectionThrottlePeriod(String powerComponentName) {
return 0;
}
@@ -150,7 +146,9 @@
mHandlerThread.start();
mHandler = mHandlerThread.getThreadHandler();
when(mMockKernelCpuStatsReader.isSupportedFeature()).thenReturn(true);
- when(mConsumedEnergyRetriever.getEnergyConsumerIds(anyInt())).thenReturn(new int[0]);
+ when(mConsumedEnergyRetriever.getEnergyConsumerIds(anyInt()))
+ .thenReturn(new int[0]);
+ when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(3500);
mUidResolver.noteIsolatedUidAdded(ISOLATED_UID, UID_2);
}
@@ -228,9 +226,7 @@
assertThat(descriptor.name).isEqualTo("cpu");
assertThat(descriptor.statsArrayLength).isEqualTo(13);
assertThat(descriptor.uidStatsArrayLength).isEqualTo(5);
- CpuPowerStatsLayout layout =
- new CpuPowerStatsLayout();
- layout.fromExtras(descriptor.extras);
+ CpuPowerStatsLayout layout = new CpuPowerStatsLayout(descriptor);
long[] deviceStats = new long[descriptor.statsArrayLength];
layout.setTimeByScalingStep(deviceStats, 2, 42);
@@ -267,8 +263,7 @@
mockEnergyConsumers();
CpuPowerStatsCollector collector = createCollector(8, 0);
- CpuPowerStatsLayout layout = new CpuPowerStatsLayout();
- layout.fromExtras(collector.getPowerStatsDescriptor().extras);
+ CpuPowerStatsLayout layout = new CpuPowerStatsLayout(collector.getPowerStatsDescriptor());
mockKernelCpuStats(new long[]{1111, 2222, 3333},
new SparseArray<>() {{
@@ -338,8 +333,7 @@
mockEnergyConsumers();
CpuPowerStatsCollector collector = createCollector(8, 0);
- CpuPowerStatsLayout layout = new CpuPowerStatsLayout();
- layout.fromExtras(collector.getPowerStatsDescriptor().extras);
+ CpuPowerStatsLayout layout = new CpuPowerStatsLayout(collector.getPowerStatsDescriptor());
mockKernelCpuStats(new long[]{1111, 2222, 3333},
new SparseArray<>() {{
@@ -462,17 +456,24 @@
private void mockEnergyConsumers() {
reset(mConsumedEnergyRetriever);
+ when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(3500);
when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.CPU_CLUSTER))
.thenReturn(new int[]{1, 2});
- when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{1, 2})))
- .thenReturn(new long[]{1000, 2000})
- .thenReturn(new long[]{1500, 2700});
+ when(mConsumedEnergyRetriever.getConsumedEnergy(eq(new int[]{1, 2})))
+ .thenReturn(new EnergyConsumerResult[]{
+ mockEnergyConsumer(1000), mockEnergyConsumer(2000)})
+ .thenReturn(new EnergyConsumerResult[]{
+ mockEnergyConsumer(1500), mockEnergyConsumer(2700)});
+ }
+
+ private EnergyConsumerResult mockEnergyConsumer(long energyUWs) {
+ EnergyConsumerResult ecr = new EnergyConsumerResult();
+ ecr.energyUWs = energyUWs;
+ return ecr;
}
private static int[] getScalingStepToPowerBracketMap(CpuPowerStatsCollector collector) {
- CpuPowerStatsLayout layout =
- new CpuPowerStatsLayout();
- layout.fromExtras(collector.getPowerStatsDescriptor().extras);
+ CpuPowerStatsLayout layout = new CpuPowerStatsLayout(collector.getPowerStatsDescriptor());
return layout.getScalingStepToPowerBracketMap();
}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsCollectorTest.java
index ef20946..00b911b 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsCollectorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsCollectorTest.java
@@ -33,6 +33,7 @@
import android.annotation.NonNull;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerResult;
import android.hardware.power.stats.EnergyConsumerType;
import android.net.NetworkStats;
import android.os.BatteryConsumer;
@@ -51,6 +52,7 @@
import com.android.internal.os.Clock;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.MobileRadioPowerStatsLayout;
import org.junit.Before;
import org.junit.Rule;
@@ -63,7 +65,6 @@
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
-import java.util.function.IntSupplier;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
@@ -139,11 +140,6 @@
}
@Override
- public IntSupplier getVoltageSupplier() {
- return () -> 3500;
- }
-
- @Override
public Supplier<NetworkStats> getMobileNetworkStatsSupplier() {
return mNetworkStatsSupplier;
}
@@ -178,6 +174,7 @@
return uid;
}
});
+ when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(3500);
mBatteryStats = mStatsRule.getBatteryStats();
}
@@ -242,8 +239,7 @@
assertThat(powerStats.durationMs).isEqualTo(100);
PowerStats.Descriptor descriptor = powerStats.descriptor;
- MobileRadioPowerStatsLayout layout =
- new MobileRadioPowerStatsLayout(descriptor);
+ MobileRadioPowerStatsLayout layout = new MobileRadioPowerStatsLayout(descriptor);
assertThat(layout.getDeviceSleepTime(powerStats.stats)).isEqualTo(200);
assertThat(layout.getDeviceIdleTime(powerStats.stats)).isEqualTo(300);
assertThat(layout.getDeviceCallTime(powerStats.stats)).isEqualTo(40000);
@@ -252,7 +248,7 @@
.isEqualTo((64321 - 10000) * 1000 / 3500);
assertThat(powerStats.stateStats.size()).isEqualTo(2);
- long[] state1 = powerStats.stateStats.get(MobileRadioPowerStatsCollector.makeStateKey(
+ long[] state1 = powerStats.stateStats.get(MobileRadioPowerStatsLayout.makeStateKey(
BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
ServiceState.FREQUENCY_RANGE_MMWAVE
));
@@ -263,7 +259,7 @@
assertThat(layout.getStateTxTime(state1, 3)).isEqualTo(4000);
assertThat(layout.getStateTxTime(state1, 4)).isEqualTo(5000);
- long[] state2 = powerStats.stateStats.get(MobileRadioPowerStatsCollector.makeStateKey(
+ long[] state2 = powerStats.stateStats.get(MobileRadioPowerStatsLayout.makeStateKey(
BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
ServiceState.FREQUENCY_RANGE_LOW
));
@@ -298,15 +294,14 @@
assertThat(powerStats.durationMs).isEqualTo(100);
PowerStats.Descriptor descriptor = powerStats.descriptor;
- MobileRadioPowerStatsLayout layout =
- new MobileRadioPowerStatsLayout(descriptor);
+ MobileRadioPowerStatsLayout layout = new MobileRadioPowerStatsLayout(descriptor);
assertThat(layout.getDeviceSleepTime(powerStats.stats)).isEqualTo(200);
assertThat(layout.getDeviceIdleTime(powerStats.stats)).isEqualTo(300);
assertThat(layout.getConsumedEnergy(powerStats.stats, 0))
.isEqualTo((64321 - 10000) * 1000 / 3500);
assertThat(powerStats.stateStats.size()).isEqualTo(1);
- long[] stateStats = powerStats.stateStats.get(MobileRadioPowerStatsCollector.makeStateKey(
+ long[] stateStats = powerStats.stateStats.get(MobileRadioPowerStatsLayout.makeStateKey(
AccessNetworkConstants.AccessNetworkType.UNKNOWN,
ServiceState.FREQUENCY_RANGE_UNKNOWN
));
@@ -416,8 +411,8 @@
4321, 321, 1234, 23,
4000, 40, 2000, 20);
- when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{777})))
- .thenReturn(new long[]{10000});
+ when(mConsumedEnergyRetriever.getConsumedEnergy(eq(new int[]{777})))
+ .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(10000)});
when(mCallDurationSupplier.getAsLong()).thenReturn(10000L);
when(mScanDurationSupplier.getAsLong()).thenReturn(20000L);
@@ -439,8 +434,8 @@
5321, 421, 3234, 223,
8000, 80, 4000, 40);
- when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{777})))
- .thenReturn(new long[]{64321});
+ when(mConsumedEnergyRetriever.getConsumedEnergy(eq(new int[]{777})))
+ .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(64321)});
when(mCallDurationSupplier.getAsLong()).thenReturn(50000L);
when(mScanDurationSupplier.getAsLong()).thenReturn(80000L);
@@ -448,6 +443,12 @@
return collector.collectStats();
}
+ private EnergyConsumerResult mockEnergyConsumer(long energyUWs) {
+ EnergyConsumerResult ecr = new EnergyConsumerResult();
+ ecr.energyUWs = energyUWs;
+ return ecr;
+ }
+
private void mockModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs,
int networkType1, int freqRange1, int rxTimeMs1, @NonNull int[] txTimeMs1,
int networkType2, int freqRange2, int rxTimeMs2, @NonNull int[] txTimeMs2) {
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsCollectorTest.java
index 89d6c1c..a04f721 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsCollectorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsCollectorTest.java
@@ -114,13 +114,15 @@
mockEnergyConsumers(powerStatsInternal);
PowerStatsCollector.ConsumedEnergyRetrieverImpl retriever =
- new PowerStatsCollector.ConsumedEnergyRetrieverImpl(powerStatsInternal);
+ new PowerStatsCollector.ConsumedEnergyRetrieverImpl(powerStatsInternal, ()-> 3500);
int[] energyConsumerIds = retriever.getEnergyConsumerIds(EnergyConsumerType.CPU_CLUSTER);
assertThat(energyConsumerIds).isEqualTo(new int[]{1, 2});
- long[] energy = retriever.getConsumedEnergyUws(energyConsumerIds);
- assertThat(energy).isEqualTo(new long[]{1000, 2000});
- energy = retriever.getConsumedEnergyUws(energyConsumerIds);
- assertThat(energy).isEqualTo(new long[]{1500, 2700});
+ EnergyConsumerResult[] energy = retriever.getConsumedEnergy(energyConsumerIds);
+ assertThat(energy[0].energyUWs).isEqualTo(1000);
+ assertThat(energy[1].energyUWs).isEqualTo(2000);
+ energy = retriever.getConsumedEnergy(energyConsumerIds);
+ assertThat(energy[0].energyUWs).isEqualTo(1500);
+ assertThat(energy[1].energyUWs).isEqualTo(2700);
}
@SuppressWarnings("unchecked")
@@ -176,4 +178,11 @@
.thenReturn(future1)
.thenReturn(future2);
}
+
+ private EnergyConsumerResult mockEnergyConsumerResult(long energyUWs) {
+ EnergyConsumerResult ecr = new EnergyConsumerResult();
+ ecr.energyUWs = energyUWs;
+ return ecr;
+ }
+
}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsSchedulerTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsSchedulerTest.java
index beec661..143d046 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsSchedulerTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsSchedulerTest.java
@@ -18,36 +18,18 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.os.ConditionVariable;
-import android.os.Handler;
-import android.os.HandlerThread;
import android.platform.test.ravenwood.RavenwoodRule;
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.os.MonotonicClock;
-
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.IOException;
-import java.nio.file.Files;
import java.time.Duration;
import java.time.Instant;
-import java.util.ArrayList;
-import java.util.List;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
-import java.util.function.Consumer;
@RunWith(AndroidJUnit4.class)
public class PowerStatsSchedulerTest {
@@ -56,134 +38,10 @@
.setProvideMainThread(true)
.build();
- private PowerStatsStore mPowerStatsStore;
- private Handler mHandler;
- private MockClock mClock = new MockClock();
- private MonotonicClock mMonotonicClock = new MonotonicClock(0, mClock);
- private PowerStatsScheduler mPowerStatsScheduler;
- private PowerStatsAggregator mPowerStatsAggregator;
- private AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
- private List<Long> mScheduledAlarms = new ArrayList<>();
- private boolean mPowerStatsCollectionOccurred;
-
- private static final int START_REALTIME = 7654321;
-
- @Before
- @SuppressWarnings("GuardedBy")
- public void setup() throws IOException {
- TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
-
- mClock.currentTime = Instant.parse("2023-01-02T03:04:05.00Z").toEpochMilli();
- mClock.realtime = START_REALTIME;
-
- HandlerThread bgThread = new HandlerThread("bg thread");
- bgThread.start();
- mHandler = new Handler(bgThread.getLooper());
- mAggregatedPowerStatsConfig = new AggregatedPowerStatsConfig();
- mPowerStatsStore = new PowerStatsStore(
- Files.createTempDirectory("PowerStatsSchedulerTest").toFile(),
- mHandler, mAggregatedPowerStatsConfig);
- mPowerStatsAggregator = mock(PowerStatsAggregator.class);
- mPowerStatsScheduler = new PowerStatsScheduler(
- () -> mPowerStatsCollectionOccurred = true,
- mPowerStatsAggregator, TimeUnit.MINUTES.toMillis(30), TimeUnit.HOURS.toMillis(1),
- mPowerStatsStore,
- ((triggerAtMillis, tag, onAlarmListener, handler) ->
- mScheduledAlarms.add(triggerAtMillis)),
- mClock, mMonotonicClock, () -> 12345L, mHandler);
- }
-
- @Test
- @SuppressWarnings("unchecked")
- public void storeAggregatePowerStats() {
- mPowerStatsStore.reset();
-
- assertThat(mPowerStatsStore.getTableOfContents()).isEmpty();
-
- mPowerStatsStore.storeAggregatedPowerStats(
- createAggregatedPowerStats(mMonotonicClock.monotonicTime(), mClock.currentTime,
- 123));
-
- long delayBeforeAggregating = TimeUnit.MINUTES.toMillis(90);
- mClock.realtime += delayBeforeAggregating;
- mClock.currentTime += delayBeforeAggregating;
-
- doAnswer(invocation -> {
- // The first span is longer than 30 min, because the end time is being aligned with
- // the wall clock. Subsequent spans should be precisely 30 minutes.
- long startTime = invocation.getArgument(0);
- long endTime = invocation.getArgument(1);
- Consumer<AggregatedPowerStats> consumer = invocation.getArgument(2);
-
- long startTimeWallClock =
- mClock.currentTime - (mMonotonicClock.monotonicTime() - startTime);
- long endTimeWallClock =
- mClock.currentTime - (mMonotonicClock.monotonicTime() - endTime);
-
- assertThat(startTime).isEqualTo(START_REALTIME + 123);
- assertThat(endTime - startTime).isAtLeast(TimeUnit.MINUTES.toMillis(30));
- assertThat(Instant.ofEpochMilli(endTimeWallClock))
- .isEqualTo(Instant.parse("2023-01-02T04:00:00Z"));
-
- consumer.accept(
- createAggregatedPowerStats(startTime, startTimeWallClock, endTime - startTime));
- return null;
- }).doAnswer(invocation -> {
- long startTime = invocation.getArgument(0);
- long endTime = invocation.getArgument(1);
- Consumer<AggregatedPowerStats> consumer = invocation.getArgument(2);
-
- long startTimeWallClock =
- mClock.currentTime - (mMonotonicClock.monotonicTime() - startTime);
- long endTimeWallClock =
- mClock.currentTime - (mMonotonicClock.monotonicTime() - endTime);
-
- assertThat(Instant.ofEpochMilli(startTimeWallClock))
- .isEqualTo(Instant.parse("2023-01-02T04:00:00Z"));
- assertThat(Instant.ofEpochMilli(endTimeWallClock))
- .isEqualTo(Instant.parse("2023-01-02T04:30:00Z"));
-
- consumer.accept(
- createAggregatedPowerStats(startTime, startTimeWallClock, endTime - startTime));
- return null;
- }).when(mPowerStatsAggregator).aggregatePowerStats(anyLong(), anyLong(),
- any(Consumer.class));
-
- mPowerStatsScheduler.start(/*enabled*/ true);
- ConditionVariable done = new ConditionVariable();
- mHandler.post(done::open);
- done.block();
-
- assertThat(mPowerStatsCollectionOccurred).isTrue();
- assertThat(mScheduledAlarms).containsExactly(
- START_REALTIME + TimeUnit.MINUTES.toMillis(90) + TimeUnit.HOURS.toMillis(1));
-
- verify(mPowerStatsAggregator, times(2))
- .aggregatePowerStats(anyLong(), anyLong(), any(Consumer.class));
-
- List<PowerStatsSpan.Metadata> contents = mPowerStatsStore.getTableOfContents();
- assertThat(contents).hasSize(3);
- // Skip the first entry, which was placed in the store at the beginning of this test
- PowerStatsSpan.TimeFrame timeFrame1 = contents.get(1).getTimeFrames().get(0);
- PowerStatsSpan.TimeFrame timeFrame2 = contents.get(2).getTimeFrames().get(0);
- assertThat(timeFrame1.startMonotonicTime).isEqualTo(START_REALTIME + 123);
- assertThat(timeFrame2.startMonotonicTime)
- .isEqualTo(timeFrame1.startMonotonicTime + timeFrame1.duration);
- assertThat(Instant.ofEpochMilli(timeFrame2.startTime))
- .isEqualTo(Instant.parse("2023-01-02T04:00:00Z"));
- assertThat(Duration.ofMillis(timeFrame2.duration)).isEqualTo(Duration.ofMinutes(30));
- }
-
- private AggregatedPowerStats createAggregatedPowerStats(long monotonicTime, long currentTime,
- long duration) {
- AggregatedPowerStats stats = new AggregatedPowerStats(mAggregatedPowerStatsConfig);
- stats.addClockUpdate(monotonicTime, currentTime);
- stats.setDuration(duration);
- return stats;
- }
-
@Test
public void alignToWallClock() {
+ TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+
// Expect the aligned value to be adjusted by 1 min 30 sec - rounded to the next 15 min
assertThat(PowerStatsScheduler.alignToWallClock(123, TimeUnit.MINUTES.toMillis(15),
123 + TimeUnit.HOURS.toMillis(2),
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsStoreTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsStoreTest.java
index 36d7af5..dc8d920 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsStoreTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsStoreTest.java
@@ -59,14 +59,7 @@
clearDirectory(mStoreDirectory);
mPowerStatsStore = new PowerStatsStore(mStoreDirectory,
- MAX_BATTERY_STATS_SNAPSHOT_STORAGE_BYTES,
- new TestHandler(),
- (sectionType, parser) -> {
- if (sectionType.equals(TestSection.TYPE)) {
- return TestSection.readXml(parser);
- }
- return null;
- });
+ MAX_BATTERY_STATS_SNAPSHOT_STORAGE_BYTES, new TestHandler());
}
@Test
@@ -144,7 +137,7 @@
}
@Override
- void write(TypedXmlSerializer serializer) throws IOException {
+ public void write(TypedXmlSerializer serializer) throws IOException {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < mSize; i++) {
sb.append("X");
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/ScreenPowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/ScreenPowerStatsCollectorTest.java
index 817fdcb..8c09d1d 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/ScreenPowerStatsCollectorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/ScreenPowerStatsCollectorTest.java
@@ -23,6 +23,7 @@
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.when;
+import android.hardware.power.stats.EnergyConsumerResult;
import android.hardware.power.stats.EnergyConsumerType;
import android.os.BatteryConsumer;
import android.os.BatteryStats;
@@ -32,6 +33,7 @@
import com.android.internal.os.Clock;
import com.android.internal.os.PowerStats;
import com.android.server.power.stats.ScreenPowerStatsCollector.Injector;
+import com.android.server.power.stats.format.ScreenPowerStatsLayout;
import org.junit.Before;
import org.junit.Rule;
@@ -39,8 +41,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.function.IntSupplier;
-
public class ScreenPowerStatsCollectorTest {
private static final int APP_UID1 = 42;
private static final int APP_UID2 = 24;
@@ -89,11 +89,6 @@
}
@Override
- public IntSupplier getVoltageSupplier() {
- return () -> 3500;
- }
-
- @Override
public int getDisplayCount() {
return 2;
}
@@ -115,6 +110,7 @@
return uid;
}
});
+ when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(3500);
}
@Test
@@ -125,8 +121,8 @@
// Establish a baseline
when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.DISPLAY))
.thenReturn(new int[]{77});
- when(mConsumedEnergyRetriever.getConsumedEnergyUws(new int[]{77}))
- .thenReturn(new long[]{10_000});
+ when(mConsumedEnergyRetriever.getConsumedEnergy(new int[]{77}))
+ .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(10_000)});
doAnswer(inv -> {
ScreenPowerStatsCollector.ScreenUsageTimeRetriever.Callback callback =
@@ -139,8 +135,8 @@
collector.collectStats();
- when(mConsumedEnergyRetriever.getConsumedEnergyUws(new int[]{77}))
- .thenReturn(new long[]{45_000});
+ when(mConsumedEnergyRetriever.getConsumedEnergy(new int[]{77}))
+ .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(45_000)});
when(mScreenUsageTimeRetriever.getScreenOnTimeMs(0))
.thenReturn(60_000L);
when(mScreenUsageTimeRetriever.getBrightnessLevelTimeMs(0,
@@ -171,8 +167,7 @@
PowerStats powerStats = collector.collectStats();
- ScreenPowerStatsLayout layout = new ScreenPowerStatsLayout();
- layout.fromExtras(powerStats.descriptor.extras);
+ ScreenPowerStatsLayout layout = new ScreenPowerStatsLayout(powerStats.descriptor);
// (45000 - 10000) / 3500
assertThat(layout.getConsumedEnergy(powerStats.stats, 0))
@@ -204,4 +199,10 @@
assertThat(layout.getUidTopActivityDuration(powerStats.uidStats.get(APP_UID2)))
.isEqualTo(10000);
}
+
+ private EnergyConsumerResult mockEnergyConsumer(long energyUWs) {
+ EnergyConsumerResult ecr = new EnergyConsumerResult();
+ ecr.energyUWs = energyUWs;
+ return ecr;
+ }
}
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
index b13fc53..8b5e6ee 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsCollectorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsCollectorTest.java
@@ -32,6 +32,7 @@
import android.content.Context;
import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerResult;
import android.hardware.power.stats.EnergyConsumerType;
import android.net.NetworkStats;
import android.net.wifi.WifiManager;
@@ -47,6 +48,7 @@
import com.android.internal.os.Clock;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.format.WifiPowerStatsLayout;
import org.junit.Before;
import org.junit.Rule;
@@ -57,7 +59,6 @@
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 {
@@ -154,11 +155,6 @@
}
@Override
- public IntSupplier getVoltageSupplier() {
- return () -> 3500;
- }
-
- @Override
public Supplier<NetworkStats> getWifiNetworkStatsSupplier() {
return mNetworkStatsSupplier;
}
@@ -368,6 +364,7 @@
WifiPowerStatsCollector collector = new WifiPowerStatsCollector(mInjector, null);
collector.setEnabled(true);
+ when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(3500);
when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.WIFI))
.thenReturn(new int[]{777});
@@ -385,8 +382,8 @@
mockWifiScanTimes(APP_UID2, 3000, 4000);
mockWifiScanTimes(ISOLATED_UID, 5000, 6000);
- when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{777})))
- .thenReturn(new long[]{10000});
+ when(mConsumedEnergyRetriever.getConsumedEnergy(eq(new int[]{777})))
+ .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(10_000)});
collector.collectStats();
@@ -404,13 +401,19 @@
mockWifiScanTimes(APP_UID2, 3100, 4200);
mockWifiScanTimes(ISOLATED_UID, 5300, 6400);
- when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{777})))
- .thenReturn(new long[]{64321});
+ when(mConsumedEnergyRetriever.getConsumedEnergy(eq(new int[]{777})))
+ .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(64_321)});
mStatsRule.setTime(20000, 20000);
return collector.collectStats();
}
+ private EnergyConsumerResult mockEnergyConsumer(long energyUWs) {
+ EnergyConsumerResult ecr = new EnergyConsumerResult();
+ ecr.energyUWs = energyUWs;
+ return ecr;
+ }
+
private void mockWifiActivityInfo(long timestamp, long rxTimeMs, long txTimeMs, int scanTimeMs,
int idleTimeMs) {
int stackState = 0;
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/AggregatedPowerStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/AggregatedPowerStatsTest.java
similarity index 93%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/AggregatedPowerStatsTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/AggregatedPowerStatsTest.java
index 04d53de..0e73329 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/AggregatedPowerStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/AggregatedPowerStatsTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import static com.google.common.truth.Truth.assertThat;
@@ -49,7 +49,8 @@
private static final int COMPONENT_STATE_1 = 1;
private static final int COMPONENT_STATE_2 = 2;
- private AggregatedPowerStatsConfig mAggregatedPowerStatsConfig;
+ private AggregatedPowerStatsConfig
+ mAggregatedPowerStatsConfig;
private PowerStats.Descriptor mPowerComponentDescriptor;
@Before
@@ -67,7 +68,8 @@
mAggregatedPowerStatsConfig.trackCustomPowerComponents(
() -> new PowerStatsProcessor() {
@Override
- void finish(PowerComponentAggregatedPowerStats stats,
+ void finish(
+ PowerComponentAggregatedPowerStats stats,
long timestampMs) {
}
})
@@ -103,8 +105,8 @@
TypedXmlPullParser parser = Xml.newFastPullParser();
parser.setInput(new ByteArrayInputStream(baos.toByteArray()), "UTF-8");
- AggregatedPowerStats actualStats = AggregatedPowerStats.createFromXml(parser,
- mAggregatedPowerStatsConfig);
+ AggregatedPowerStats actualStats =
+ AggregatedPowerStats.createFromXml(parser, mAggregatedPowerStatsConfig);
verifyAggregatedPowerStats(actualStats);
}
@@ -163,7 +165,8 @@
return stats;
}
- private void verifyAggregatedPowerStats(AggregatedPowerStats stats) {
+ private void verifyAggregatedPowerStats(
+ AggregatedPowerStats stats) {
PowerStats.Descriptor descriptor = stats.getPowerComponentStats(TEST_POWER_COMPONENT)
.getPowerStatsDescriptor();
assertThat(descriptor.powerComponentId).isEqualTo(TEST_POWER_COMPONENT);
@@ -277,7 +280,8 @@
.isEqualTo(new long[]{250, 300});
}
- private static long[] getDeviceStats(AggregatedPowerStats stats, int powerComponentId,
+ private static long[] getDeviceStats(
+ AggregatedPowerStats stats, int powerComponentId,
int... states) {
PowerComponentAggregatedPowerStats powerComponentStats =
stats.getPowerComponentStats(powerComponentId);
@@ -286,7 +290,8 @@
return out;
}
- private static long[] getStateStats(AggregatedPowerStats stats, int key, int... states) {
+ private static long[] getStateStats(
+ AggregatedPowerStats stats, int key, int... states) {
PowerComponentAggregatedPowerStats powerComponentStats =
stats.getPowerComponentStats(TEST_POWER_COMPONENT);
long[] out = new long[powerComponentStats.getPowerStatsDescriptor().stateStatsArrayLength];
@@ -294,7 +299,8 @@
return out;
}
- private static long[] getUidDeviceStats(AggregatedPowerStats stats, int powerComponentId,
+ private static long[] getUidDeviceStats(
+ AggregatedPowerStats stats, int powerComponentId,
int uid, int... states) {
PowerComponentAggregatedPowerStats powerComponentStats =
stats.getPowerComponentStats(powerComponentId);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/AmbientDisplayPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessorTest.java
similarity index 68%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/AmbientDisplayPowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessorTest.java
index a2a7e00..21e615f 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/AmbientDisplayPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessorTest.java
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
-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_SCREEN;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
import static com.google.common.truth.Truth.assertThat;
@@ -35,7 +35,12 @@
import com.android.internal.os.Clock;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.PowerStats;
-import com.android.server.power.stats.ScreenPowerStatsCollector.Injector;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.PowerStatsCollector;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.ScreenPowerStatsCollector;
+import com.android.server.power.stats.ScreenPowerStatsCollector.ScreenUsageTimeRetriever;
+import com.android.server.power.stats.format.PowerStatsLayout;
import org.junit.Before;
import org.junit.Rule;
@@ -43,8 +48,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.function.IntSupplier;
-
public class AmbientDisplayPowerStatsProcessorTest {
@Rule(order = 0)
@@ -64,49 +67,45 @@
@Mock
private PowerStatsCollector.ConsumedEnergyRetriever mConsumedEnergyRetriever;
@Mock
- private ScreenPowerStatsCollector.ScreenUsageTimeRetriever mScreenUsageTimeRetriever;
+ private ScreenUsageTimeRetriever mScreenUsageTimeRetriever;
- private final Injector mInjector = new Injector() {
- @Override
- public Handler getHandler() {
- return mStatsRule.getHandler();
- }
+ private final ScreenPowerStatsCollector.Injector mInjector =
+ new ScreenPowerStatsCollector.Injector() {
+ @Override
+ public Handler getHandler() {
+ return mStatsRule.getHandler();
+ }
- @Override
- public Clock getClock() {
- return mStatsRule.getMockClock();
- }
+ @Override
+ public Clock getClock() {
+ return mStatsRule.getMockClock();
+ }
- @Override
- public PowerStatsUidResolver getUidResolver() {
- return new PowerStatsUidResolver();
- }
+ @Override
+ public PowerStatsUidResolver getUidResolver() {
+ return new PowerStatsUidResolver();
+ }
- @Override
- public long getPowerStatsCollectionThrottlePeriod(String powerComponentName) {
- return 0;
- }
+ @Override
+ public long getPowerStatsCollectionThrottlePeriod(String powerComponentName) {
+ return 0;
+ }
- @Override
- public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
- return mConsumedEnergyRetriever;
- }
+ @Override
+ public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
+ return mConsumedEnergyRetriever;
+ }
- @Override
- public IntSupplier getVoltageSupplier() {
- return () -> VOLTAGE_MV;
- }
+ @Override
+ public int getDisplayCount() {
+ return 2;
+ }
- @Override
- public int getDisplayCount() {
- return 2;
- }
-
- @Override
- public ScreenPowerStatsCollector.ScreenUsageTimeRetriever getScreenUsageTimeRetriever() {
- return mScreenUsageTimeRetriever;
- }
- };
+ @Override
+ public ScreenUsageTimeRetriever getScreenUsageTimeRetriever() {
+ return mScreenUsageTimeRetriever;
+ }
+ };
@Before
public void setup() {
@@ -167,7 +166,8 @@
return stats.getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY);
}
- private void assertPowerEstimate(PowerComponentAggregatedPowerStats aggregatedStats,
+ private void assertPowerEstimate(
+ PowerComponentAggregatedPowerStats aggregatedStats,
int powerState, int screenState, double expectedPowerEstimate) {
PowerStats.Descriptor descriptor = aggregatedStats.getPowerStatsDescriptor();
PowerStatsLayout layout = new PowerStatsLayout(descriptor);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BinaryStatePowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessorTest.java
similarity index 92%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/BinaryStatePowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessorTest.java
index 4b40f68..b412ad6 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BinaryStatePowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BinaryStatePowerStatsProcessorTest.java
@@ -14,19 +14,19 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
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.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
import static com.google.common.truth.Truth.assertThat;
@@ -40,6 +40,9 @@
import com.android.internal.os.MonotonicClock;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.MockClock;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.format.BinaryStatePowerStatsLayout;
import org.junit.Rule;
import org.junit.Test;
@@ -146,7 +149,8 @@
@Test
public void energyConsumerModel() {
- BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout();
+ BinaryStatePowerStatsLayout
+ statsLayout = new BinaryStatePowerStatsLayout();
PersistableBundle extras = new PersistableBundle();
statsLayout.toExtras(extras);
PowerStats.Descriptor descriptor = new PowerStats.Descriptor(POWER_COMPONENT,
@@ -270,9 +274,8 @@
.trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
.setProcessorSupplier(processorSupplier);
- AggregatedPowerStats aggregatedPowerStats = new AggregatedPowerStats(config);
PowerComponentAggregatedPowerStats powerComponentStats =
- aggregatedPowerStats.getPowerComponentStats(POWER_COMPONENT);
+ new AggregatedPowerStats(config).getPowerComponentStats(POWER_COMPONENT);
powerComponentStats.start(0);
powerComponentStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BluetoothPowerStatsProcessorTest.java
similarity index 91%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/BluetoothPowerStatsProcessorTest.java
index 4a8125f..6dfc220 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BluetoothPowerStatsProcessorTest.java
@@ -14,19 +14,19 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
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.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
import static com.google.common.truth.Truth.assertThat;
@@ -38,6 +38,7 @@
import android.bluetooth.UidTraffic;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerResult;
import android.hardware.power.stats.EnergyConsumerType;
import android.os.BatteryConsumer;
import android.os.Handler;
@@ -48,7 +49,12 @@
import com.android.internal.os.Clock;
import com.android.internal.os.PowerProfile;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.BluetoothPowerStatsCollector;
import com.android.server.power.stats.BluetoothPowerStatsCollector.BluetoothStatsRetriever;
+import com.android.server.power.stats.PowerStatsCollector;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.format.BluetoothPowerStatsLayout;
import org.junit.Before;
import org.junit.Rule;
@@ -58,7 +64,6 @@
import java.util.List;
import java.util.concurrent.Executor;
-import java.util.function.IntSupplier;
import java.util.function.Supplier;
public class BluetoothPowerStatsProcessorTest {
@@ -143,11 +148,6 @@
}
@Override
- public IntSupplier getVoltageSupplier() {
- return () -> VOLTAGE_MV;
- }
-
- @Override
public BluetoothStatsRetriever getBluetoothStatsRetriever() {
return mBluetoothStatsRetriever;
}
@@ -363,7 +363,8 @@
@Test
public void consumedEnergyModel() {
- // No power monitoring hardware
+ when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(VOLTAGE_MV);
+ // Power monitoring hardware exists
when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.BLUETOOTH))
.thenReturn(new int[]{BLUETOOTH_ENERGY_CONSUMER_ID});
@@ -378,8 +379,8 @@
mUidScanTimes.put(APP_UID1, 100);
- when(mConsumedEnergyRetriever.getConsumedEnergyUws(
- new int[]{BLUETOOTH_ENERGY_CONSUMER_ID})).thenReturn(new long[]{0});
+ when(mConsumedEnergyRetriever.getConsumedEnergy(new int[]{BLUETOOTH_ENERGY_CONSUMER_ID}))
+ .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(0)});
aggregatedStats.start(0);
@@ -404,8 +405,8 @@
// 10 mAh represented as microWattSeconds
long energyUws = 10 * 3600 * VOLTAGE_MV;
- when(mConsumedEnergyRetriever.getConsumedEnergyUws(
- new int[]{BLUETOOTH_ENERGY_CONSUMER_ID})).thenReturn(new long[]{energyUws});
+ when(mConsumedEnergyRetriever.getConsumedEnergy(new int[]{BLUETOOTH_ENERGY_CONSUMER_ID}))
+ .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(energyUws)});
aggregatedStats.addPowerStats(collector.collectStats(), 10_000);
@@ -468,16 +469,15 @@
private static PowerComponentAggregatedPowerStats createAggregatedPowerStats(
Supplier<PowerStatsProcessor> processorSupplier) {
- AggregatedPowerStatsConfig.PowerComponent config =
- new AggregatedPowerStatsConfig.PowerComponent(
- BatteryConsumer.POWER_COMPONENT_BLUETOOTH)
- .trackDeviceStates(STATE_POWER, STATE_SCREEN)
- .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
- .setProcessorSupplier(processorSupplier);
+ AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_BLUETOOTH)
+ .trackDeviceStates(STATE_POWER, STATE_SCREEN)
+ .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
+ .setProcessorSupplier(processorSupplier);
PowerComponentAggregatedPowerStats aggregatedStats =
- new PowerComponentAggregatedPowerStats(
- new AggregatedPowerStats(mock(AggregatedPowerStatsConfig.class)), config);
+ new AggregatedPowerStats(config).getPowerComponentStats(
+ BatteryConsumer.POWER_COMPONENT_BLUETOOTH);
aggregatedStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_ON, 0);
@@ -491,6 +491,12 @@
return states;
}
+ private EnergyConsumerResult mockEnergyConsumer(long energyUWs) {
+ EnergyConsumerResult ecr = new EnergyConsumerResult();
+ ecr.energyUWs = energyUWs;
+ return ecr;
+ }
+
private BluetoothActivityEnergyInfo mockBluetoothActivityEnergyInfo(long timestamp,
long rxTimeMs, long txTimeMs, long idleTimeMs, UidTraffic... uidTraffic) {
if (RavenwoodRule.isOnRavenwood()) {
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/CameraPowerStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CameraPowerStatsTest.java
similarity index 88%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/CameraPowerStatsTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/CameraPowerStatsTest.java
index 88a4f5e..0afcbf1 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/CameraPowerStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CameraPowerStatsTest.java
@@ -14,23 +14,22 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
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.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
@@ -46,6 +45,12 @@
import com.android.internal.os.MonotonicClock;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.CameraPowerStatsCollector;
+import com.android.server.power.stats.EnergyConsumerPowerStatsCollector;
+import com.android.server.power.stats.PowerStatsCollector;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.format.BinaryStatePowerStatsLayout;
import org.junit.Before;
import org.junit.Rule;
@@ -53,7 +58,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.function.IntSupplier;
import java.util.function.Supplier;
public class CameraPowerStatsTest {
@@ -103,11 +107,6 @@
public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
return mConsumedEnergyRetriever;
}
-
- @Override
- public IntSupplier getVoltageSupplier() {
- return () -> VOLTAGE_MV;
- }
};
private MonotonicClock mMonotonicClock;
@@ -120,8 +119,9 @@
@Test
public void energyConsumerModel() {
+ when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(VOLTAGE_MV);
when(mConsumedEnergyRetriever
- .getEnergyConsumerIds(eq((int) EnergyConsumerType.CAMERA), any()))
+ .getEnergyConsumerIds(eq((int) EnergyConsumerType.CAMERA)))
.thenReturn(new int[]{ENERGY_CONSUMER_ID});
PowerComponentAggregatedPowerStats stats = createAggregatedPowerStats(
@@ -161,8 +161,7 @@
stats.finish(11_000);
PowerStats.Descriptor descriptor = stats.getPowerStatsDescriptor();
- BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout();
- statsLayout.fromExtras(descriptor.extras);
+ BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout(descriptor);
// Total estimated power = 3,600,000 uC = 1.0 mAh
// of which 3,000,000 is distributed:
@@ -243,7 +242,8 @@
private static PowerComponentAggregatedPowerStats createAggregatedPowerStats(
Supplier<PowerStatsProcessor> processorSupplier) {
- AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
+ AggregatedPowerStatsConfig
+ config = new AggregatedPowerStatsConfig();
config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_CAMERA)
.trackDeviceStates(
AggregatedPowerStatsConfig.STATE_POWER,
@@ -254,9 +254,8 @@
AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
.setProcessorSupplier(processorSupplier);
- AggregatedPowerStats aggregatedPowerStats = new AggregatedPowerStats(config);
- PowerComponentAggregatedPowerStats powerComponentStats =
- aggregatedPowerStats.getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_CAMERA);
+ PowerComponentAggregatedPowerStats powerComponentStats = new AggregatedPowerStats(config)
+ .getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_CAMERA);
powerComponentStats.start(0);
powerComponentStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CpuPowerStatsProcessorTest.java
similarity index 86%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/CpuPowerStatsProcessorTest.java
index ab2e631..6938615 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/CpuPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CpuPowerStatsProcessorTest.java
@@ -13,24 +13,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
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 com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
-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.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
import android.os.BatteryConsumer;
import android.os.PersistableBundle;
@@ -42,6 +41,8 @@
import com.android.internal.os.PowerProfile;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.format.CpuPowerStatsLayout;
import org.junit.Before;
import org.junit.Rule;
@@ -202,26 +203,18 @@
PowerComponentAggregatedPowerStats {
private final CpuPowerStatsLayout mStatsLayout;
private final PowerStats.Descriptor mDescriptor;
- private HashMap<String, long[]> mDeviceStats = new HashMap<>();
- private HashMap<String, long[]> mUidStats = new HashMap<>();
- private HashSet<Integer> mUids = new HashSet<>();
- private HashMap<String, Double> mExpectedDevicePower = new HashMap<>();
- private HashMap<String, Double> mExpectedUidPower = new HashMap<>();
+ private final HashMap<String, long[]> mDeviceStats = new HashMap<>();
+ private final HashMap<String, long[]> mUidStats = new HashMap<>();
+ private final HashSet<Integer> mUids = new HashSet<>();
+ private final HashMap<String, Double> mExpectedDevicePower = new HashMap<>();
+ private final HashMap<String, Double> mExpectedUidPower = new HashMap<>();
- MockPowerComponentAggregatedPowerStats(AggregatedPowerStatsConfig.PowerComponent config,
+ MockPowerComponentAggregatedPowerStats(
+ AggregatedPowerStatsConfig.PowerComponent config,
boolean useEnergyConsumers) {
- super(new AggregatedPowerStats(mock(AggregatedPowerStatsConfig.class)), config);
- mStatsLayout = new CpuPowerStatsLayout();
- mStatsLayout.addDeviceSectionCpuTimeByScalingStep(3);
- mStatsLayout.addDeviceSectionCpuTimeByCluster(2);
- mStatsLayout.addDeviceSectionUsageDuration();
- if (useEnergyConsumers) {
- mStatsLayout.addDeviceSectionEnergyConsumers(2);
- }
- mStatsLayout.addDeviceSectionPowerEstimate();
- mStatsLayout.addUidSectionCpuTimeByPowerBracket(new int[]{0, 1, 2});
- mStatsLayout.addUidSectionPowerEstimate();
-
+ super(new AggregatedPowerStats(new AggregatedPowerStatsConfig()), config);
+ mStatsLayout = new CpuPowerStatsLayout(useEnergyConsumers ? 2 : 0, 2,
+ new int[]{0, 1, 2});
PersistableBundle extras = new PersistableBundle();
mStatsLayout.toExtras(extras);
mDescriptor = new PowerStats.Descriptor(BatteryConsumer.POWER_COMPONENT_CPU,
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/CustomEnergyConsumerPowerStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsTest.java
similarity index 90%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/CustomEnergyConsumerPowerStatsTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsTest.java
index 8239fdb..42baba7 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/CustomEnergyConsumerPowerStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/CustomEnergyConsumerPowerStatsTest.java
@@ -14,20 +14,20 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
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_BATTERY;
-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.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
import static com.google.common.truth.Truth.assertThat;
@@ -42,6 +42,12 @@
import com.android.internal.os.Clock;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.CustomEnergyConsumerPowerStatsCollector;
+import com.android.server.power.stats.EnergyConsumerPowerStatsCollector;
+import com.android.server.power.stats.PowerStatsCollector;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.format.EnergyConsumerPowerStatsLayout;
import org.junit.Before;
import org.junit.Rule;
@@ -54,7 +60,6 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
-import java.util.function.IntSupplier;
public class CustomEnergyConsumerPowerStatsTest {
@Rule(order = 0)
@@ -105,11 +110,6 @@
public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
return mConsumedEnergyRetriever;
}
-
- @Override
- public IntSupplier getVoltageSupplier() {
- return () -> VOLTAGE_MV;
- }
};
@@ -237,6 +237,7 @@
private List<PowerStats> collectPowerStats(long timestamp, int chargeUc1, int chargeUc2,
EnergyConsumerAttribution... attributions2) throws Exception {
+ when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(VOLTAGE_MV);
when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.OTHER))
.thenReturn(new int[]{ENERGY_CONSUMER_ID1, ENERGY_CONSUMER_ID2});
when(mConsumedEnergyRetriever.getEnergyConsumerName(ENERGY_CONSUMER_ID1))
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/GnssPowerStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/GnssPowerStatsTest.java
similarity index 93%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/GnssPowerStatsTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/GnssPowerStatsTest.java
index f22279a..e6207d4 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/GnssPowerStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/GnssPowerStatsTest.java
@@ -14,23 +14,22 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
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.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
@@ -47,6 +46,12 @@
import com.android.internal.os.MonotonicClock;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.EnergyConsumerPowerStatsCollector;
+import com.android.server.power.stats.GnssPowerStatsCollector;
+import com.android.server.power.stats.PowerStatsCollector;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.format.BinaryStatePowerStatsLayout;
import org.junit.Before;
import org.junit.Rule;
@@ -54,7 +59,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.function.IntSupplier;
import java.util.function.Supplier;
public class GnssPowerStatsTest {
@@ -106,11 +110,6 @@
public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
return mConsumedEnergyRetriever;
}
-
- @Override
- public IntSupplier getVoltageSupplier() {
- return () -> VOLTAGE_MV;
- }
};
private MonotonicClock mMonotonicClock;
@@ -127,7 +126,7 @@
public void powerProfileModel() {
// ODPM unsupported
when(mConsumedEnergyRetriever
- .getEnergyConsumerIds(eq((int) EnergyConsumerType.GNSS), any()))
+ .getEnergyConsumerIds(eq((int) EnergyConsumerType.GNSS)))
.thenReturn(new int[0]);
PowerComponentAggregatedPowerStats stats = createAggregatedPowerStats(
@@ -165,8 +164,7 @@
stats.finish(START_TIME + 11_000);
PowerStats.Descriptor descriptor = stats.getPowerStatsDescriptor();
- BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout();
- statsLayout.fromExtras(descriptor.extras);
+ BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout(descriptor);
// scr-on, GNSS-good: 2500 * 100 = 250000 mA-ms = 0.06944 mAh
// scr-off GNSS=good: 4500 * 100 = 0.12500 mAh
@@ -218,7 +216,7 @@
public void initialStateGnssOn() {
// ODPM unsupported
when(mConsumedEnergyRetriever
- .getEnergyConsumerIds(eq((int) EnergyConsumerType.GNSS), any()))
+ .getEnergyConsumerIds(eq((int) EnergyConsumerType.GNSS)))
.thenReturn(new int[0]);
PowerComponentAggregatedPowerStats stats = createAggregatedPowerStats(
@@ -245,8 +243,7 @@
stats.finish(START_TIME + 11_000);
PowerStats.Descriptor descriptor = stats.getPowerStatsDescriptor();
- BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout();
- statsLayout.fromExtras(descriptor.extras);
+ BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout(descriptor);
// scr-on, GNSS-good: 2500 * 100 = 250000 mA-ms = 0.06944 mAh
// scr-off GNSS=good: 4500 * 100 = 0.12500 mAh
@@ -296,8 +293,9 @@
@Test
public void energyConsumerModel() {
+ when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(VOLTAGE_MV);
when(mConsumedEnergyRetriever
- .getEnergyConsumerIds(eq((int) EnergyConsumerType.GNSS), any()))
+ .getEnergyConsumerIds(eq((int) EnergyConsumerType.GNSS)))
.thenReturn(new int[]{ENERGY_CONSUMER_ID});
PowerComponentAggregatedPowerStats stats = createAggregatedPowerStats(
@@ -339,8 +337,7 @@
stats.finish(START_TIME + 11_000);
PowerStats.Descriptor descriptor = stats.getPowerStatsDescriptor();
- BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout();
- statsLayout.fromExtras(descriptor.extras);
+ BinaryStatePowerStatsLayout statsLayout = new BinaryStatePowerStatsLayout(descriptor);
// Total estimated power = 3,600,000 uC = 1.0 mAh
// of which 3,000,000 is distributed:
@@ -442,7 +439,8 @@
private static PowerComponentAggregatedPowerStats createAggregatedPowerStats(
Supplier<PowerStatsProcessor> processorSupplier) {
- AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
+ AggregatedPowerStatsConfig
+ config = new AggregatedPowerStatsConfig();
config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_GNSS)
.trackDeviceStates(
AggregatedPowerStatsConfig.STATE_POWER,
@@ -453,9 +451,8 @@
AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
.setProcessorSupplier(processorSupplier);
- AggregatedPowerStats aggregatedPowerStats = new AggregatedPowerStats(config);
- PowerComponentAggregatedPowerStats powerComponentStats =
- aggregatedPowerStats.getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_GNSS);
+ PowerComponentAggregatedPowerStats powerComponentStats = new AggregatedPowerStats(config)
+ .getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_GNSS);
powerComponentStats.start(START_TIME);
powerComponentStats.setState(STATE_POWER, POWER_STATE_OTHER, START_TIME);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessorTest.java
similarity index 87%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessorTest.java
index 89d59a9..80358c5 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/MobileRadioPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MobileRadioPowerStatsProcessorTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
import static android.net.NetworkStats.METERED_NO;
@@ -23,12 +23,12 @@
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.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
import static com.google.common.truth.Truth.assertThat;
@@ -41,6 +41,7 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerResult;
import android.hardware.power.stats.EnergyConsumerType;
import android.net.NetworkStats;
import android.os.BatteryConsumer;
@@ -53,6 +54,11 @@
import com.android.internal.os.Clock;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.MobileRadioPowerStatsCollector;
+import com.android.server.power.stats.PowerStatsCollector;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.format.MobileRadioPowerStatsLayout;
import org.junit.Before;
import org.junit.Rule;
@@ -61,7 +67,6 @@
import org.mockito.MockitoAnnotations;
import java.util.List;
-import java.util.function.IntSupplier;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
@@ -129,11 +134,6 @@
}
@Override
- public IntSupplier getVoltageSupplier() {
- return () -> VOLTAGE_MV;
- }
-
- @Override
public Supplier<NetworkStats> getMobileNetworkStatsSupplier() {
return mNetworkStatsSupplier;
}
@@ -172,17 +172,15 @@
mStatsRule.setTestPowerProfile("power_profile_test_modem_calculator");
- AggregatedPowerStatsConfig.PowerComponent config =
- new AggregatedPowerStatsConfig.PowerComponent(
- BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
- .trackDeviceStates(STATE_POWER, STATE_SCREEN)
- .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
- .setProcessorSupplier(() -> new MobileRadioPowerStatsProcessor(
- mStatsRule.getPowerProfile()));
+ AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
+ .trackDeviceStates(STATE_POWER, STATE_SCREEN)
+ .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
+ .setProcessorSupplier(
+ () -> new MobileRadioPowerStatsProcessor(mStatsRule.getPowerProfile()));
- PowerComponentAggregatedPowerStats aggregatedStats =
- new PowerComponentAggregatedPowerStats(
- new AggregatedPowerStats(mock(AggregatedPowerStatsConfig.class)), config);
+ PowerComponentAggregatedPowerStats aggregatedStats = new AggregatedPowerStats(config)
+ .getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO);
aggregatedStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_ON, 0);
@@ -232,8 +230,7 @@
aggregatedStats.finish(10_000);
MobileRadioPowerStatsLayout statsLayout =
- new MobileRadioPowerStatsLayout(
- aggregatedStats.getPowerStatsDescriptor());
+ new MobileRadioPowerStatsLayout(aggregatedStats.getPowerStatsDescriptor());
// 720 mA * 100 ms (level 0 TX drain rate * level 0 TX duration)
// + 1080 mA * 200 ms (level 1 TX drain rate * level 1 TX duration)
@@ -316,8 +313,7 @@
prepareAggregatedStats_energyConsumerModel();
MobileRadioPowerStatsLayout statsLayout =
- new MobileRadioPowerStatsLayout(
- aggregatedStats.getPowerStatsDescriptor());
+ new MobileRadioPowerStatsLayout(aggregatedStats.getPowerStatsDescriptor());
// 10_000_000 micro-Coulomb * 1/1000 milli/micro * 1/3600 hour/second = 2.77778 mAh
double totalPower = 0;
@@ -406,23 +402,22 @@
private PowerComponentAggregatedPowerStats prepareAggregatedStats_energyConsumerModel() {
// PowerStats hardware is available
+ when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(VOLTAGE_MV);
when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.MOBILE_RADIO))
.thenReturn(new int[] {MOBILE_RADIO_ENERGY_CONSUMER_ID});
mStatsRule.setTestPowerProfile("power_profile_test_legacy_modem")
.initMeasuredEnergyStatsLocked();
- AggregatedPowerStatsConfig.PowerComponent config =
- new AggregatedPowerStatsConfig.PowerComponent(
- BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
- .trackDeviceStates(STATE_POWER, STATE_SCREEN)
- .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
- .setProcessorSupplier(() -> new MobileRadioPowerStatsProcessor(
- mStatsRule.getPowerProfile()));
+ AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
+ .trackDeviceStates(STATE_POWER, STATE_SCREEN)
+ .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
+ .setProcessorSupplier(
+ () -> new MobileRadioPowerStatsProcessor(mStatsRule.getPowerProfile()));
- PowerComponentAggregatedPowerStats aggregatedStats =
- new PowerComponentAggregatedPowerStats(
- new AggregatedPowerStats(mock(AggregatedPowerStatsConfig.class)), config);
+ PowerComponentAggregatedPowerStats aggregatedStats = new AggregatedPowerStats(config)
+ .getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO);
aggregatedStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_ON, 0);
@@ -436,9 +431,9 @@
// Initial empty ModemActivityInfo.
mockModemActivityInfo(new ModemActivityInfo(0L, 0L, 0L, new int[5], 0L));
- when(mConsumedEnergyRetriever.getConsumedEnergyUws(
+ when(mConsumedEnergyRetriever.getConsumedEnergy(
new int[]{MOBILE_RADIO_ENERGY_CONSUMER_ID}))
- .thenReturn(new long[]{0});
+ .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(0)});
aggregatedStats.start(0);
@@ -467,8 +462,8 @@
mStatsRule.setTime(10_000, 10_000);
long energyUws = 10_000_000L * VOLTAGE_MV / 1000L;
- when(mConsumedEnergyRetriever.getConsumedEnergyUws(
- new int[]{MOBILE_RADIO_ENERGY_CONSUMER_ID})).thenReturn(new long[]{energyUws});
+ when(mConsumedEnergyRetriever.getConsumedEnergy(new int[]{MOBILE_RADIO_ENERGY_CONSUMER_ID}))
+ .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(energyUws)});
when(mCallDurationSupplier.getAsLong()).thenReturn(200L);
when(mScanDurationSupplier.getAsLong()).thenReturn(5555L);
@@ -485,6 +480,12 @@
return states;
}
+ private EnergyConsumerResult mockEnergyConsumer(long energyUWs) {
+ EnergyConsumerResult ecr = new EnergyConsumerResult();
+ ecr.energyUWs = energyUWs;
+ return ecr;
+ }
+
private void mockModemActivityInfo(ModemActivityInfo emptyMai) {
doAnswer(invocation -> {
OutcomeReceiver<ModemActivityInfo, TelephonyManager.ModemActivityInfoException>
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStatePowerAttributorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStatePowerAttributorTest.java
new file mode 100644
index 0000000..704ee62
--- /dev/null
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStatePowerAttributorTest.java
@@ -0,0 +1,183 @@
+/*
+ * 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.processor;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.os.ConditionVariable;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.platform.test.ravenwood.RavenwoodRule;
+
+import com.android.internal.os.BatteryStatsHistory;
+import com.android.internal.os.MonotonicClock;
+import com.android.server.power.stats.MockClock;
+import com.android.server.power.stats.PowerStatsScheduler;
+import com.android.server.power.stats.PowerStatsSpan;
+import com.android.server.power.stats.PowerStatsStore;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TimeZone;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+public class MultiStatePowerAttributorTest {
+
+ @Rule
+ public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+ .setProvideMainThread(true)
+ .build();
+
+ private PowerStatsStore mPowerStatsStore;
+ private Handler mHandler;
+ private final MockClock mClock = new MockClock();
+ private final MonotonicClock mMonotonicClock = new MonotonicClock(0, mClock);
+ private PowerStatsScheduler mPowerStatsScheduler;
+ private PowerStatsAggregator mPowerStatsAggregator;
+ private MultiStatePowerAttributor mPowerAttributor;
+ private final List<Long> mScheduledAlarms = new ArrayList<>();
+ private boolean mPowerStatsCollectionOccurred;
+
+ private static final int START_REALTIME = 7654321;
+
+ @Before
+ public void setup() throws IOException {
+ TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+
+ mClock.currentTime = Instant.parse("2023-01-02T03:04:05.00Z").toEpochMilli();
+ mClock.realtime = START_REALTIME;
+
+ HandlerThread bgThread = new HandlerThread("bg thread");
+ bgThread.start();
+ mHandler = new Handler(bgThread.getLooper());
+ mPowerStatsStore = new PowerStatsStore(
+ Files.createTempDirectory("MultiStatePowerAttributorTest").toFile(), mHandler);
+ mPowerStatsAggregator = mock(PowerStatsAggregator.class);
+ mPowerAttributor = new MultiStatePowerAttributor(mPowerStatsStore, mPowerStatsAggregator);
+ mPowerStatsScheduler = new PowerStatsScheduler(
+ () -> mPowerStatsCollectionOccurred = true,
+ mock(BatteryStatsHistory.class),
+ mPowerAttributor, TimeUnit.MINUTES.toMillis(30), TimeUnit.HOURS.toMillis(1),
+ mPowerStatsStore,
+ ((triggerAtMillis, tag, onAlarmListener, handler) ->
+ mScheduledAlarms.add(triggerAtMillis)),
+ mClock, mMonotonicClock, () -> 12345L, mHandler);
+ }
+
+ @Test
+ public void storeAggregatedPowerStats() {
+ mPowerStatsStore.reset();
+
+ assertThat(mPowerStatsStore.getTableOfContents()).isEmpty();
+
+ mPowerAttributor.storeAggregatedPowerStats(
+ createAggregatedPowerStats(mMonotonicClock.monotonicTime(), mClock.currentTime,
+ 123));
+
+ long delayBeforeAggregating = TimeUnit.MINUTES.toMillis(90);
+ mClock.realtime += delayBeforeAggregating;
+ mClock.currentTime += delayBeforeAggregating;
+
+ doAnswer(invocation -> {
+ // The first span is longer than 30 min, because the end time is being aligned with
+ // the wall clock. Subsequent spans should be precisely 30 minutes.
+ long startTime = invocation.getArgument(1);
+ long endTime = invocation.getArgument(2);
+ Consumer<AggregatedPowerStats> consumer = invocation.getArgument(3);
+
+ long startTimeWallClock =
+ mClock.currentTime - (mMonotonicClock.monotonicTime() - startTime);
+ long endTimeWallClock =
+ mClock.currentTime - (mMonotonicClock.monotonicTime() - endTime);
+
+ assertThat(startTime).isEqualTo(START_REALTIME + 123);
+ assertThat(endTime - startTime).isAtLeast(TimeUnit.MINUTES.toMillis(30));
+ assertThat(Instant.ofEpochMilli(endTimeWallClock))
+ .isEqualTo(Instant.parse("2023-01-02T04:00:00Z"));
+
+ consumer.accept(
+ createAggregatedPowerStats(startTime, startTimeWallClock, endTime - startTime));
+ return null;
+ }).doAnswer(invocation -> {
+ long startTime = invocation.getArgument(1);
+ long endTime = invocation.getArgument(2);
+ Consumer<AggregatedPowerStats> consumer = invocation.getArgument(3);
+
+ long startTimeWallClock =
+ mClock.currentTime - (mMonotonicClock.monotonicTime() - startTime);
+ long endTimeWallClock =
+ mClock.currentTime - (mMonotonicClock.monotonicTime() - endTime);
+
+ assertThat(Instant.ofEpochMilli(startTimeWallClock))
+ .isEqualTo(Instant.parse("2023-01-02T04:00:00Z"));
+ assertThat(Instant.ofEpochMilli(endTimeWallClock))
+ .isEqualTo(Instant.parse("2023-01-02T04:30:00Z"));
+
+ consumer.accept(
+ createAggregatedPowerStats(startTime, startTimeWallClock, endTime - startTime));
+ return null;
+ }).when(mPowerStatsAggregator).aggregatePowerStats(any(BatteryStatsHistory.class),
+ anyLong(), anyLong(), any(Consumer.class));
+
+ mPowerStatsScheduler.start(/*enabled*/ true);
+ ConditionVariable done = new ConditionVariable();
+ mHandler.post(done::open);
+ done.block();
+
+ assertThat(mPowerStatsCollectionOccurred).isTrue();
+ assertThat(mScheduledAlarms).containsExactly(
+ START_REALTIME + TimeUnit.MINUTES.toMillis(90) + TimeUnit.HOURS.toMillis(1));
+
+ verify(mPowerStatsAggregator, times(2)).aggregatePowerStats(
+ any(BatteryStatsHistory.class), anyLong(), anyLong(), any(Consumer.class));
+
+ List<PowerStatsSpan.Metadata> contents = mPowerStatsStore.getTableOfContents();
+ assertThat(contents).hasSize(3);
+ // Skip the first entry, which was placed in the store at the beginning of this test
+ PowerStatsSpan.TimeFrame timeFrame1 = contents.get(1).getTimeFrames().get(0);
+ PowerStatsSpan.TimeFrame timeFrame2 = contents.get(2).getTimeFrames().get(0);
+ assertThat(timeFrame1.startMonotonicTime).isEqualTo(START_REALTIME + 123);
+ assertThat(timeFrame2.startMonotonicTime)
+ .isEqualTo(timeFrame1.startMonotonicTime + timeFrame1.duration);
+ assertThat(Instant.ofEpochMilli(timeFrame2.startTime))
+ .isEqualTo(Instant.parse("2023-01-02T04:00:00Z"));
+ assertThat(Duration.ofMillis(timeFrame2.duration)).isEqualTo(Duration.ofMinutes(30));
+ }
+
+ private AggregatedPowerStats createAggregatedPowerStats(long monotonicTime, long currentTime,
+ long duration) {
+ AggregatedPowerStats stats = new AggregatedPowerStats(new AggregatedPowerStatsConfig());
+ stats.addClockUpdate(monotonicTime, currentTime);
+ stats.setDuration(duration);
+ return stats;
+ }
+}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/MultiStateStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStateStatsTest.java
similarity index 99%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/MultiStateStatsTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStateStatsTest.java
index ae258cd3..a232c0c 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/MultiStateStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/MultiStateStatsTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -198,8 +198,7 @@
new MultiStateStats.States("scr", trackScreenState, "screen-off", "plugged-in"));
}
- private FactorySubject assertThatCpuPerformanceStatsFactory(
- MultiStateStats.Factory factory) {
+ private FactorySubject assertThatCpuPerformanceStatsFactory(MultiStateStats.Factory factory) {
FactorySubject subject = new FactorySubject();
subject.mFactory = factory;
return subject;
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PhoneCallPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessorTest.java
similarity index 84%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/PhoneCallPowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessorTest.java
index cb1bcfe..535f2da 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PhoneCallPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PhoneCallPowerStatsProcessorTest.java
@@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
-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.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
import static com.google.common.truth.Truth.assertThat;
@@ -41,6 +41,11 @@
import android.telephony.TelephonyManager;
import com.android.internal.os.Clock;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.MobileRadioPowerStatsCollector;
+import com.android.server.power.stats.PowerStatsCollector;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.format.PowerStatsLayout;
import org.junit.Before;
import org.junit.Rule;
@@ -48,7 +53,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.function.IntSupplier;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
@@ -113,11 +117,6 @@
}
@Override
- public IntSupplier getVoltageSupplier() {
- return () -> VOLTAGE_MV;
- }
-
- @Override
public Supplier<NetworkStats> getMobileNetworkStatsSupplier() {
return mNetworkStatsSupplier;
}
@@ -156,19 +155,17 @@
@Test
public void copyEstimatesFromMobileRadioPowerStats() {
-
- AggregatedPowerStatsConfig aggregatedPowerStatsConfig = new AggregatedPowerStatsConfig();
- aggregatedPowerStatsConfig.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
+ AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
.trackDeviceStates(STATE_POWER, STATE_SCREEN)
.trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
.setProcessorSupplier(
() -> new MobileRadioPowerStatsProcessor(mStatsRule.getPowerProfile()));
- aggregatedPowerStatsConfig.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_PHONE,
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_PHONE,
BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
.setProcessorSupplier(PhoneCallPowerStatsProcessor::new);
- AggregatedPowerStats aggregatedPowerStats =
- new AggregatedPowerStats(aggregatedPowerStatsConfig);
+ AggregatedPowerStats aggregatedPowerStats = new AggregatedPowerStats(config);
PowerComponentAggregatedPowerStats mobileRadioStats =
aggregatedPowerStats.getPowerComponentStats(
BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO);
@@ -208,8 +205,7 @@
aggregatedPowerStats.getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_PHONE);
stats.finish(10_000);
- PowerStatsLayout statsLayout =
- new PowerStatsLayout(stats.getPowerStatsDescriptor());
+ PowerStatsLayout statsLayout = new PowerStatsLayout(stats.getPowerStatsDescriptor());
long[] deviceStats = new long[stats.getPowerStatsDescriptor().statsArrayLength];
stats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_ON));
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PowerStatsAggregatorTest.java
similarity index 95%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/PowerStatsAggregatorTest.java
index 3929137..f312bed 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsAggregatorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PowerStatsAggregatorTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import static com.google.common.truth.Truth.assertThat;
@@ -32,6 +32,7 @@
import com.android.internal.os.BatteryStatsHistory;
import com.android.internal.os.MonotonicClock;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.MockClock;
import org.junit.Before;
import org.junit.Test;
@@ -53,7 +54,7 @@
private final MockClock mClock = new MockClock();
private final MonotonicClock mMonotonicClock = new MonotonicClock(START_TIME, mClock);
private BatteryStatsHistory mHistory;
- private PowerStatsAggregator mAggregator;
+ private com.android.server.power.stats.processor.PowerStatsAggregator mAggregator;
private int mAggregatedStatsCount;
@Before
@@ -71,7 +72,7 @@
AggregatedPowerStatsConfig.STATE_POWER,
AggregatedPowerStatsConfig.STATE_SCREEN,
AggregatedPowerStatsConfig.STATE_PROCESS_STATE);
- mAggregator = new PowerStatsAggregator(config, mHistory);
+ mAggregator = new PowerStatsAggregator(config);
}
@Test
@@ -119,7 +120,7 @@
powerStats.uidStats.put(TEST_UID, new long[]{4444});
mHistory.recordPowerStats(mClock.realtime, mClock.uptime, powerStats);
- mAggregator.aggregatePowerStats(0, MonotonicClock.UNDEFINED, stats -> {
+ mAggregator.aggregatePowerStats(mHistory, 0, MonotonicClock.UNDEFINED, stats -> {
assertThat(mAggregatedStatsCount++).isEqualTo(0);
assertThat(stats.getStartTime()).isEqualTo(START_TIME);
@@ -138,7 +139,8 @@
long[] values = new long[1];
- PowerComponentAggregatedPowerStats powerComponentStats = stats.getPowerComponentStats(
+ PowerComponentAggregatedPowerStats
+ powerComponentStats = stats.getPowerComponentStats(
TEST_POWER_COMPONENT);
assertThat(powerComponentStats.getDeviceStats(values, new int[]{
@@ -218,7 +220,7 @@
mHistory.recordBatteryState(mClock.realtime, mClock.uptime, 50, /* plugged */ true);
- mAggregator.aggregatePowerStats(0, MonotonicClock.UNDEFINED, stats -> {
+ mAggregator.aggregatePowerStats(mHistory, 0, MonotonicClock.UNDEFINED, stats -> {
long[] values = new long[1];
PowerComponentAggregatedPowerStats powerComponentStats =
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsExporterTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PowerStatsExporterTest.java
similarity index 95%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsExporterTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/PowerStatsExporterTest.java
index 96203a5..024743d 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsExporterTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PowerStatsExporterTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -22,6 +22,7 @@
import static org.mockito.Mockito.mock;
import android.annotation.NonNull;
+import android.content.Context;
import android.os.AggregateBatteryConsumer;
import android.os.BatteryConsumer;
import android.os.BatteryStats;
@@ -37,9 +38,16 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.os.BatteryStatsHistory;
+import com.android.internal.os.CpuScalingPolicies;
import com.android.internal.os.MonotonicClock;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.MockClock;
+import com.android.server.power.stats.PowerStatsStore;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.format.CpuPowerStatsLayout;
+import com.android.server.power.stats.format.EnergyConsumerPowerStatsLayout;
import org.junit.Before;
import org.junit.Rule;
@@ -76,6 +84,7 @@
private MonotonicClock mMonotonicClock = new MonotonicClock(0, mClock);
private PowerStatsStore mPowerStatsStore;
private PowerStatsAggregator mPowerStatsAggregator;
+ private MultiStatePowerAttributor mPowerAttributor;
private BatteryStatsHistory mHistory;
private CpuPowerStatsLayout mCpuStatsArrayLayout;
private PowerStats.Descriptor mPowerStatsDescriptor;
@@ -108,25 +117,23 @@
AggregatedPowerStatsConfig.STATE_SCREEN,
AggregatedPowerStatsConfig.STATE_PROCESS_STATE);
- mPowerStatsStore = new PowerStatsStore(storeDirectory, new TestHandler(), config);
+ mPowerStatsStore = new PowerStatsStore(storeDirectory, new TestHandler());
mHistory = new BatteryStatsHistory(Parcel.obtain(), storeDirectory, 0, 10000,
mock(BatteryStatsHistory.HistoryStepDetailsCalculator.class), mClock,
mMonotonicClock, null, null);
- mPowerStatsAggregator = new PowerStatsAggregator(config, mHistory);
+ mPowerStatsAggregator = new PowerStatsAggregator(config);
- mCpuStatsArrayLayout = new CpuPowerStatsLayout();
- mCpuStatsArrayLayout.addDeviceSectionCpuTimeByScalingStep(1);
- mCpuStatsArrayLayout.addDeviceSectionCpuTimeByCluster(1);
- mCpuStatsArrayLayout.addDeviceSectionUsageDuration();
- mCpuStatsArrayLayout.addDeviceSectionPowerEstimate();
- mCpuStatsArrayLayout.addUidSectionCpuTimeByPowerBracket(new int[]{0});
- mCpuStatsArrayLayout.addUidSectionPowerEstimate();
+ mCpuStatsArrayLayout = new CpuPowerStatsLayout(0, 1, new int[]{0});
PersistableBundle extras = new PersistableBundle();
mCpuStatsArrayLayout.toExtras(extras);
mPowerStatsDescriptor = new PowerStats.Descriptor(BatteryConsumer.POWER_COMPONENT_CPU,
mCpuStatsArrayLayout.getDeviceStatsArrayLength(),
null, 0, mCpuStatsArrayLayout.getUidStatsArrayLength(), extras);
+
+ mPowerAttributor = new MultiStatePowerAttributor(mock(Context.class), mPowerStatsStore,
+ mock(PowerProfile.class), mock(CpuScalingPolicies.class),
+ mock(PowerStatsUidResolver.class));
}
@Test
@@ -329,10 +336,12 @@
includeScreenStateData, includesPowerStateData);
}
- private @NonNull BatteryUsageStats exportToBatteryUsageStats(AggregatedPowerStats aps,
+ private @NonNull BatteryUsageStats exportToBatteryUsageStats(
+ AggregatedPowerStats aps,
boolean includeProcessStateData, boolean includeScreenStateData,
boolean includesPowerStateData) {
- PowerStatsExporter exporter = new PowerStatsExporter(mPowerStatsStore,
+ PowerStatsExporter
+ exporter = new PowerStatsExporter(mPowerStatsStore,
mPowerStatsAggregator, /* batterySessionTimeSpanSlackMillis */ 0);
BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(new String[0], false,
@@ -508,8 +517,8 @@
mCpuStatsArrayLayout.setUidTimeByPowerBracket(uidStats2, 0, 2469);
mHistory.recordPowerStats(3000, 3000, powerStats);
- mPowerStatsAggregator.aggregatePowerStats(0, 3500,
- stats -> mPowerStatsStore.storeAggregatedPowerStats(stats));
+ mPowerStatsAggregator.aggregatePowerStats(mHistory, 0, 3500,
+ stats -> mPowerAttributor.storeAggregatedPowerStats(stats));
mHistory.recordProcessStateChange(4000, 4000, APP_UID1,
BatteryConsumer.PROCESS_STATE_BACKGROUND);
@@ -525,9 +534,8 @@
mEnergyConsumerPowerStatsLayout.setUidConsumedEnergy(customUidStats, 0, 360_000);
mHistory.recordPowerStats(6010, 6010, customPowerStats);
- mPowerStatsAggregator.aggregatePowerStats(3500, 6500, stats -> {
- mPowerStatsStore.storeAggregatedPowerStats(stats);
- });
+ mPowerStatsAggregator.aggregatePowerStats(mHistory, 3500, 6500,
+ stats -> mPowerAttributor.storeAggregatedPowerStats(stats));
mHistory.recordStateStartEvent(7000, 7000, BatteryStats.HistoryItem.STATE_SCREEN_ON_FLAG);
mHistory.recordProcessStateChange(7000, 7000, APP_UID1,
@@ -548,7 +556,8 @@
recordBatteryHistory();
PowerStatsExporter exporter = new PowerStatsExporter(mPowerStatsStore,
mPowerStatsAggregator, /* batterySessionTimeSpanSlackMillis */ 0);
- exporter.exportAggregatedPowerStats(builder, monotonicStartTime, monotonicEndTime);
+ exporter.exportAggregatedPowerStats(builder, mHistory, monotonicStartTime,
+ monotonicEndTime);
}
private void assertAggregatedPowerEstimate(String message, BatteryUsageStats bus, int scope,
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PowerStatsProcessorTest.java
similarity index 94%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/PowerStatsProcessorTest.java
index 02e446a..13e0d9d 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/PowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/PowerStatsProcessorTest.java
@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
-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.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
import static com.google.common.truth.Truth.assertThat;
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/ScreenPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/ScreenPowerStatsProcessorTest.java
similarity index 83%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/ScreenPowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/ScreenPowerStatsProcessorTest.java
index 94f5662..1852165 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/ScreenPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/ScreenPowerStatsProcessorTest.java
@@ -14,22 +14,22 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
-import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
-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_SCREEN;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_BATTERY;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.hardware.power.stats.EnergyConsumerResult;
import android.hardware.power.stats.EnergyConsumerType;
import android.os.BatteryConsumer;
import android.os.BatteryStats;
@@ -40,7 +40,12 @@
import com.android.internal.os.Clock;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.PowerStatsCollector;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.ScreenPowerStatsCollector;
import com.android.server.power.stats.ScreenPowerStatsCollector.Injector;
+import com.android.server.power.stats.format.ScreenPowerStatsLayout;
import org.junit.Before;
import org.junit.Rule;
@@ -48,7 +53,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.function.IntSupplier;
import java.util.function.Supplier;
public class ScreenPowerStatsProcessorTest {
@@ -106,11 +110,6 @@
}
@Override
- public IntSupplier getVoltageSupplier() {
- return () -> VOLTAGE_MV;
- }
-
- @Override
public int getDisplayCount() {
return 2;
}
@@ -124,6 +123,7 @@
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
+ when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(VOLTAGE_MV);
}
@Test
@@ -177,8 +177,8 @@
if (energyConsumer) {
when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.DISPLAY))
.thenReturn(new int[]{77});
- when(mConsumedEnergyRetriever.getConsumedEnergyUws(new int[]{77}))
- .thenReturn(new long[]{10_000});
+ when(mConsumedEnergyRetriever.getConsumedEnergy(new int[]{77}))
+ .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(10_000)});
} else {
when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.DISPLAY))
.thenReturn(new int[0]);
@@ -200,8 +200,8 @@
if (energyConsumer) {
// 400 mAh represented as microWattSeconds
long energyUws = 400L * 3600 * VOLTAGE_MV;
- when(mConsumedEnergyRetriever.getConsumedEnergyUws(new int[]{77}))
- .thenReturn(new long[]{10_000 + energyUws});
+ when(mConsumedEnergyRetriever.getConsumedEnergy(new int[]{77}))
+ .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(10_000 + energyUws)});
}
when(mScreenUsageTimeRetriever.getScreenOnTimeMs(0))
@@ -243,16 +243,14 @@
private static PowerComponentAggregatedPowerStats createAggregatedPowerStats(
Supplier<PowerStatsProcessor> processorSupplier) {
- AggregatedPowerStatsConfig.PowerComponent config =
- new AggregatedPowerStatsConfig.PowerComponent(
- BatteryConsumer.POWER_COMPONENT_SCREEN)
+ AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_SCREEN)
.trackDeviceStates(STATE_POWER, STATE_SCREEN)
.trackUidStates(STATE_POWER, STATE_SCREEN)
.setProcessorSupplier(processorSupplier);
- PowerComponentAggregatedPowerStats aggregatedStats =
- new PowerComponentAggregatedPowerStats(
- new AggregatedPowerStats(mock(AggregatedPowerStatsConfig.class)), config);
+ PowerComponentAggregatedPowerStats aggregatedStats = new AggregatedPowerStats(config)
+ .getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_SCREEN);
aggregatedStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_ON, 0);
@@ -260,7 +258,14 @@
return aggregatedStats;
}
- private void assertDevicePowerEstimate(PowerComponentAggregatedPowerStats aggregatedStats,
+ private EnergyConsumerResult mockEnergyConsumer(long energyUWs) {
+ EnergyConsumerResult ecr = new EnergyConsumerResult();
+ ecr.energyUWs = energyUWs;
+ return ecr;
+ }
+
+ private void assertDevicePowerEstimate(
+ PowerComponentAggregatedPowerStats aggregatedStats,
int powerState, int screenState, double expectedScreenPowerEstimate,
double expectedDozePowerEstimate) {
PowerStats.Descriptor descriptor = aggregatedStats.getPowerStatsDescriptor();
@@ -273,7 +278,8 @@
.of(expectedDozePowerEstimate);
}
- private void assertUidPowerEstimate(PowerComponentAggregatedPowerStats aggregatedStats, int uid,
+ private void assertUidPowerEstimate(
+ PowerComponentAggregatedPowerStats aggregatedStats, int uid,
int powerState, int screenState, double expectedScreenPowerEstimate) {
PowerStats.Descriptor descriptor = aggregatedStats.getPowerStatsDescriptor();
ScreenPowerStatsLayout layout = new ScreenPowerStatsLayout(descriptor);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/SensorPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/SensorPowerStatsProcessorTest.java
similarity index 91%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/SensorPowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/SensorPowerStatsProcessorTest.java
index 687d70b..d972604 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/SensorPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/SensorPowerStatsProcessorTest.java
@@ -14,19 +14,19 @@
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
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.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
import static com.google.common.truth.Truth.assertThat;
@@ -43,6 +43,8 @@
import com.android.internal.os.MonotonicClock;
import com.android.internal.os.PowerStats;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.format.SensorPowerStatsLayout;
import org.junit.Before;
import org.junit.Rule;
@@ -109,8 +111,7 @@
stats.finish(10000);
PowerStats.Descriptor descriptor = stats.getPowerStatsDescriptor();
- SensorPowerStatsLayout statsLayout = new SensorPowerStatsLayout();
- statsLayout.fromExtras(descriptor.extras);
+ SensorPowerStatsLayout statsLayout = new SensorPowerStatsLayout(descriptor);
String dump = stats.toString();
assertThat(dump).contains(" step_counter: ");
@@ -207,10 +208,8 @@
AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
.setProcessorSupplier(processorSupplier);
- AggregatedPowerStats aggregatedPowerStats = new AggregatedPowerStats(config);
- PowerComponentAggregatedPowerStats powerComponentStats =
- aggregatedPowerStats.getPowerComponentStats(
- BatteryConsumer.POWER_COMPONENT_SENSORS);
+ PowerComponentAggregatedPowerStats powerComponentStats = new AggregatedPowerStats(config)
+ .getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_SENSORS);
powerComponentStats.start(0);
powerComponentStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/WifiPowerStatsProcessorTest.java
similarity index 91%
rename from services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsProcessorTest.java
rename to services/tests/powerstatstests/src/com/android/server/power/stats/processor/WifiPowerStatsProcessorTest.java
index 11c09bc..baf468e 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsProcessorTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/WifiPowerStatsProcessorTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.power.stats;
+package com.android.server.power.stats.processor;
import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
import static android.net.NetworkStats.METERED_NO;
@@ -23,12 +23,12 @@
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.android.server.power.stats.processor.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.processor.AggregatedPowerStatsConfig.STATE_SCREEN;
import static com.google.common.truth.Truth.assertThat;
@@ -41,6 +41,7 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerResult;
import android.hardware.power.stats.EnergyConsumerType;
import android.net.NetworkStats;
import android.net.wifi.WifiManager;
@@ -53,6 +54,13 @@
import com.android.internal.os.Clock;
import com.android.internal.os.PowerProfile;
+import com.android.server.power.stats.BatteryUsageStatsRule;
+import com.android.server.power.stats.MockBatteryStatsImpl;
+import com.android.server.power.stats.PowerStatsCollector;
+import com.android.server.power.stats.PowerStatsUidResolver;
+import com.android.server.power.stats.WifiPowerStatsCollector;
+import com.android.server.power.stats.WifiPowerStatsCollector.WifiStatsRetriever;
+import com.android.server.power.stats.format.WifiPowerStatsLayout;
import org.junit.Before;
import org.junit.Rule;
@@ -61,7 +69,6 @@
import org.mockito.MockitoAnnotations;
import java.util.List;
-import java.util.function.IntSupplier;
import java.util.function.Supplier;
public class WifiPowerStatsProcessorTest {
@@ -109,8 +116,7 @@
private final SparseArray<ScanTimes> mScanTimes = new SparseArray<>();
private long mWifiActiveDuration;
- private final WifiPowerStatsCollector.WifiStatsRetriever mWifiStatsRetriever =
- new WifiPowerStatsCollector.WifiStatsRetriever() {
+ private final WifiStatsRetriever mWifiStatsRetriever = new WifiStatsRetriever() {
@Override
public void retrieveWifiScanTimes(Callback callback) {
for (int i = 0; i < mScanTimes.size(); i++) {
@@ -159,11 +165,6 @@
}
@Override
- public IntSupplier getVoltageSupplier() {
- return () -> VOLTAGE_MV;
- }
-
- @Override
public Supplier<NetworkStats> getWifiNetworkStatsSupplier() {
return mNetworkStatsSupplier;
}
@@ -174,7 +175,7 @@
}
@Override
- public WifiPowerStatsCollector.WifiStatsRetriever getWifiStatsRetriever() {
+ public WifiStatsRetriever getWifiStatsRetriever() {
return mWifiStatsRetriever;
}
};
@@ -308,6 +309,7 @@
when(mWifiManager.isEnhancedPowerReportingSupported()).thenReturn(true);
// PowerStats hardware is available
+ when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(VOLTAGE_MV);
when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.WIFI))
.thenReturn(new int[] {WIFI_ENERGY_CONSUMER_ID});
@@ -321,9 +323,9 @@
mockWifiActivityEnergyInfo(new WifiActivityEnergyInfo(0L,
WifiActivityEnergyInfo.STACK_STATE_INVALID, 0L, 0L, 0L, 0L));
- when(mConsumedEnergyRetriever.getConsumedEnergyUws(
+ when(mConsumedEnergyRetriever.getConsumedEnergy(
new int[]{WIFI_ENERGY_CONSUMER_ID}))
- .thenReturn(new long[]{0});
+ .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(0)});
aggregatedStats.start(0);
@@ -354,8 +356,8 @@
// 10 mAh represented as microWattSeconds
long energyUws = 10 * 3600 * VOLTAGE_MV;
- when(mConsumedEnergyRetriever.getConsumedEnergyUws(
- new int[]{WIFI_ENERGY_CONSUMER_ID})).thenReturn(new long[]{energyUws});
+ when(mConsumedEnergyRetriever.getConsumedEnergy(new int[]{WIFI_ENERGY_CONSUMER_ID}))
+ .thenReturn(new EnergyConsumerResult[]{mockEnergyConsumer(energyUws)});
aggregatedStats.addPowerStats(collector.collectStats(), 10_000);
@@ -525,15 +527,14 @@
private static PowerComponentAggregatedPowerStats createAggregatedPowerStats(
Supplier<PowerStatsProcessor> processorSupplier) {
- AggregatedPowerStatsConfig.PowerComponent config =
- new AggregatedPowerStatsConfig.PowerComponent(BatteryConsumer.POWER_COMPONENT_WIFI)
- .trackDeviceStates(STATE_POWER, STATE_SCREEN)
- .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
- .setProcessorSupplier(processorSupplier);
+ AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig();
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_WIFI)
+ .trackDeviceStates(STATE_POWER, STATE_SCREEN)
+ .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
+ .setProcessorSupplier(processorSupplier);
- PowerComponentAggregatedPowerStats aggregatedStats =
- new PowerComponentAggregatedPowerStats(
- new AggregatedPowerStats(mock(AggregatedPowerStatsConfig.class)), config);
+ PowerComponentAggregatedPowerStats aggregatedStats = new AggregatedPowerStats(config)
+ .getPowerComponentStats(BatteryConsumer.POWER_COMPONENT_WIFI);
aggregatedStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_ON, 0);
@@ -547,6 +548,12 @@
return states;
}
+ private EnergyConsumerResult mockEnergyConsumer(long energyUWs) {
+ EnergyConsumerResult ecr = new EnergyConsumerResult();
+ ecr.energyUWs = energyUWs;
+ return ecr;
+ }
+
private void mockWifiActivityEnergyInfo(WifiActivityEnergyInfo waei) {
doAnswer(invocation -> {
WifiManager.OnWifiActivityEnergyInfoListener
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 09f81f7..a862c43 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -678,3 +678,176 @@
test_suites: ["device-tests"],
include_filters: ["com.android.server.input"],
}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_job",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.job"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_tare",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.tare"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_usage",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.usage"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_om",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.om"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_accessibility",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.accessibility"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_binarytransparencyservicetest",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.BinaryTransparencyServiceTest"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_pinnerservicetest",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.PinnerServiceTest"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_am",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.am."],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_hdmi",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.hdmi"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_logcat",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.logcat"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_net_Presubmit",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.net."],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_policy_Presubmit",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.policy."],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_policy",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.policy."],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_power",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.power"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_power_hint",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.power.hint"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_location_contexthub_Postsubmit",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.location.contexthub."],
+ include_annotations: ["android.platform.test.annotations.Postsubmit"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_input",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.input"],
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MouseKeysInterceptorTest.kt b/services/tests/servicestests/src/com/android/server/accessibility/MouseKeysInterceptorTest.kt
index 8753b25..019ccf9 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MouseKeysInterceptorTest.kt
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MouseKeysInterceptorTest.kt
@@ -48,6 +48,7 @@
import java.util.LinkedList
import java.util.Queue
import android.util.ArraySet
+import android.view.InputDevice
/**
* Tests for {@link MouseKeysInterceptor}
@@ -68,6 +69,8 @@
}
private lateinit var mouseKeysInterceptor: MouseKeysInterceptor
+ private lateinit var inputDevice: InputDevice
+
private val clock = OffsettableClock()
private val testLooper = TestLooper { clock.now() }
private val nextInterceptor = TrackingInterceptor()
@@ -98,6 +101,10 @@
testSession = InputManagerGlobal.createTestSession(iInputManager)
mockInputManager = InputManager(context)
+ inputDevice = createInputDevice(DEVICE_ID)
+ Mockito.`when`(iInputManager.getInputDevice(DEVICE_ID))
+ .thenReturn(inputDevice)
+
Mockito.`when`(mockVirtualDeviceManagerInternal.getDeviceIdsForUid(Mockito.anyInt()))
.thenReturn(ArraySet(setOf(DEVICE_ID)))
LocalServices.removeServiceForTest(VirtualDeviceManagerInternal::class.java)
@@ -115,7 +122,8 @@
Mockito.`when`(iInputManager.inputDeviceIds).thenReturn(intArrayOf(DEVICE_ID))
Mockito.`when`(mockAms.traceManager).thenReturn(mockTraceManager)
- mouseKeysInterceptor = MouseKeysInterceptor(mockAms, testLooper.looper, DISPLAY_ID)
+ mouseKeysInterceptor = MouseKeysInterceptor(mockAms, mockInputManager,
+ testLooper.looper, DISPLAY_ID)
mouseKeysInterceptor.next = nextInterceptor
}
@@ -281,6 +289,17 @@
}
}
+ private fun createInputDevice(
+ deviceId: Int,
+ generation: Int = -1
+ ): InputDevice =
+ InputDevice.Builder()
+ .setId(deviceId)
+ .setName("Device $deviceId")
+ .setDescriptor("descriptor $deviceId")
+ .setGeneration(generation)
+ .build()
+
private class TrackingInterceptor : BaseEventStreamTransformation() {
val events: Queue<KeyEvent> = LinkedList()
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java
index 1cd61e9..e5005d1 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java
@@ -44,6 +44,8 @@
import android.graphics.PointF;
import android.os.Looper;
import android.os.SystemClock;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.testing.DexmakerShareClassLoaderRule;
import android.view.InputDevice;
import android.view.MotionEvent;
@@ -56,6 +58,7 @@
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.accessibility.AccessibilityTraceManager;
import com.android.server.accessibility.EventStreamTransformation;
+import com.android.server.accessibility.Flags;
import com.android.server.accessibility.utils.GestureLogParser;
import com.android.server.testutils.OffsettableClock;
@@ -119,6 +122,9 @@
public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
new DexmakerShareClassLoaderRule();
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
/**
* {@link TouchExplorer#sendDownForAllNotInjectedPointers} injecting events with the same object
* is resulting {@link ArgumentCaptor} to capture events with last state. Before implementation
@@ -154,18 +160,43 @@
mHandler = new TestHandler();
mTouchExplorer = new TouchExplorer(mContext, mMockAms, null, mHandler);
mTouchExplorer.setNext(mCaptor);
+ // Start TouchExplorer in the state where it has already reset InputDispatcher so that
+ // all tests do not start with an irrelevant ACTION_CANCEL.
+ mTouchExplorer.setHasResetInputDispatcherState(true);
}
@Test
public void testOneFingerMove_shouldInjectHoverEvents() {
- goFromStateClearTo(STATE_TOUCH_EXPLORING_1FINGER);
- // Wait for transiting to touch exploring state.
+ triggerTouchExplorationWithOneFingerDownMoveUp();
+ assertCapturedEvents(ACTION_HOVER_ENTER, ACTION_HOVER_MOVE, ACTION_HOVER_EXIT);
+ assertState(STATE_TOUCH_EXPLORING);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_RESET_INPUT_DISPATCHER_BEFORE_FIRST_TOUCH_EXPLORATION)
+ public void testStartTouchExploration_shouldResetInputDispatcherStateWithActionCancel() {
+ // Start TouchExplorer in the state where it has *not yet* reset InputDispatcher.
+ mTouchExplorer.setHasResetInputDispatcherState(false);
+ // Trigger touch exploration twice, with a handler fast-forward in between so TouchExplorer
+ // treats these as two separate interactions.
+ triggerTouchExplorationWithOneFingerDownMoveUp();
+ mHandler.fastForward(2 * USER_INTENT_TIMEOUT);
+ triggerTouchExplorationWithOneFingerDownMoveUp();
+
+ assertCapturedEvents(
+ ACTION_CANCEL, // Only one ACTION_CANCEL before the first touch exploration
+ ACTION_HOVER_ENTER, ACTION_HOVER_MOVE, ACTION_HOVER_EXIT,
+ ACTION_HOVER_ENTER, ACTION_HOVER_MOVE, ACTION_HOVER_EXIT);
+ assertState(STATE_TOUCH_EXPLORING);
+ }
+
+ private void triggerTouchExplorationWithOneFingerDownMoveUp() {
+ send(downEvent());
+ // Fast forward so that TouchExplorer's timeouts transition us to the touch exploring state.
mHandler.fastForward(2 * USER_INTENT_TIMEOUT);
moveEachPointers(mLastEvent, p(10, 10));
send(mLastEvent);
- goToStateClearFrom(STATE_TOUCH_EXPLORING_1FINGER);
- assertCapturedEvents(ACTION_HOVER_ENTER, ACTION_HOVER_MOVE, ACTION_HOVER_EXIT);
- assertState(STATE_TOUCH_EXPLORING);
+ send(upEvent());
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 0c92abc..b9ce8ad 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -1163,16 +1163,6 @@
verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
Bundle result = mBundleCaptor.getValue();
- Bundle sessionBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
- assertNotNull(sessionBundle);
- // Assert that session bundle is decrypted and hence data is visible.
- assertEquals(AccountManagerServiceTestFixtures.SESSION_DATA_VALUE_1,
- sessionBundle.getString(AccountManagerServiceTestFixtures.SESSION_DATA_NAME_1));
- // Assert finishSessionAsUser added calling uid and pid into the sessionBundle
- assertTrue(sessionBundle.containsKey(AccountManager.KEY_CALLER_UID));
- assertTrue(sessionBundle.containsKey(AccountManager.KEY_CALLER_PID));
- assertEquals(sessionBundle.getString(
- AccountManager.KEY_ANDROID_PACKAGE_NAME), "APCT.package");
// Verify response data
assertNull(result.getString(AccountManager.KEY_AUTHTOKEN, null));
@@ -2121,12 +2111,6 @@
result.getString(AccountManager.KEY_ACCOUNT_NAME));
assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
result.getString(AccountManager.KEY_ACCOUNT_TYPE));
-
- Bundle optionBundle = result.getParcelable(
- AccountManagerServiceTestFixtures.KEY_OPTIONS_BUNDLE);
- // Assert addAccountAsUser added calling uid and pid into the option bundle
- assertTrue(optionBundle.containsKey(AccountManager.KEY_CALLER_UID));
- assertTrue(optionBundle.containsKey(AccountManager.KEY_CALLER_PID));
}
@SmallTest
@@ -3457,6 +3441,52 @@
+ (readTotalTime.doubleValue() / readerCount / loopSize));
}
+ @SmallTest
+ public void testSanitizeBundle_expectedFields() throws Exception {
+ Bundle bundle = new Bundle();
+ bundle.putString(AccountManager.KEY_ACCOUNT_NAME, "name");
+ bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, "type");
+ bundle.putString(AccountManager.KEY_AUTHTOKEN, "token");
+ bundle.putString(AccountManager.KEY_AUTH_TOKEN_LABEL, "label");
+ bundle.putString(AccountManager.KEY_ERROR_MESSAGE, "error message");
+ bundle.putString(AccountManager.KEY_PASSWORD, "password");
+ bundle.putString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN, "status");
+
+ bundle.putLong(AbstractAccountAuthenticator.KEY_CUSTOM_TOKEN_EXPIRY, 123L);
+ bundle.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
+ bundle.putInt(AccountManager.KEY_ERROR_CODE, 456);
+
+ Bundle sanitizedBundle = AccountManagerService.sanitizeBundle(bundle);
+ assertEquals(sanitizedBundle.getString(AccountManager.KEY_ACCOUNT_NAME), "name");
+ assertEquals(sanitizedBundle.getString(AccountManager.KEY_ACCOUNT_TYPE), "type");
+ assertEquals(sanitizedBundle.getString(AccountManager.KEY_AUTHTOKEN), "token");
+ assertEquals(sanitizedBundle.getString(AccountManager.KEY_AUTH_TOKEN_LABEL), "label");
+ assertEquals(sanitizedBundle.getString(AccountManager.KEY_ERROR_MESSAGE), "error message");
+ assertEquals(sanitizedBundle.getString(AccountManager.KEY_PASSWORD), "password");
+ assertEquals(sanitizedBundle.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN), "status");
+
+ assertEquals(sanitizedBundle.getLong(
+ AbstractAccountAuthenticator.KEY_CUSTOM_TOKEN_EXPIRY, 0), 123L);
+ assertEquals(sanitizedBundle.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false), true);
+ assertEquals(sanitizedBundle.getInt(AccountManager.KEY_ERROR_CODE, 0), 456);
+ }
+
+ @SmallTest
+ public void testSanitizeBundle_filtersUnexpectedFields() throws Exception {
+ Bundle bundle = new Bundle();
+ bundle.putString(AccountManager.KEY_ACCOUNT_NAME, "name");
+ bundle.putString("unknown_key", "value");
+ Bundle sessionBundle = new Bundle();
+ bundle.putBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
+
+ Bundle sanitizedBundle = AccountManagerService.sanitizeBundle(bundle);
+
+ assertEquals(sanitizedBundle.getString(AccountManager.KEY_ACCOUNT_NAME), "name");
+ assertFalse(sanitizedBundle.containsKey("unknown_key"));
+ // It is a valid response from Authenticator which will be accessed using original Bundle
+ assertFalse(sanitizedBundle.containsKey(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE));
+ }
+
private void waitForCyclicBarrier(CyclicBarrier cyclicBarrier) {
try {
cyclicBarrier.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index 2a55521..a25621a 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -90,6 +90,7 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IRemoteCallback;
+import android.os.IpcDataCache;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManagerInternal;
@@ -197,6 +198,9 @@
@Before
public void setUp() throws Exception {
runWithDexmakerShareClassLoader(() -> {
+ // Disable binder caches in this process.
+ IpcDataCache.disableForTestMode();
+
mInjector = spy(new TestInjector(getInstrumentation().getTargetContext()));
doNothing().when(mInjector).clearAllLockedTasks(anyString());
doNothing().when(mInjector).startHomeActivity(anyInt(), anyString());
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
index 4c3a233..760d38e 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
@@ -264,6 +264,22 @@
assertThat(preAuthInfo.eligibleSensors).hasSize(0);
}
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
+ public void testMandatoryBiometricsNegativeButtonText_whenSet()
+ throws Exception {
+ when(mTrustManager.isInSignificantPlace()).thenReturn(false);
+
+ final BiometricSensor sensor = getFaceSensor();
+ final PromptInfo promptInfo = new PromptInfo();
+ promptInfo.setAuthenticators(BiometricManager.Authenticators.MANDATORY_BIOMETRICS);
+ promptInfo.setNegativeButtonText(TEST_PACKAGE_NAME);
+ final PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager,
+ mSettingObserver, List.of(sensor), 0 /* userId */, promptInfo, TEST_PACKAGE_NAME,
+ false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager);
+ assertThat(promptInfo.getNegativeButtonText()).isEqualTo(TEST_PACKAGE_NAME);
+ }
+
private BiometricSensor getFingerprintSensor() {
BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FINGERPRINT,
TYPE_FINGERPRINT, BiometricManager.Authenticators.BIOMETRIC_STRONG,
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java
index 6ace9f1..fca0cfb 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/BaseAbsoluteVolumeBehaviorTest.java
@@ -20,6 +20,7 @@
import static com.android.server.hdmi.HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP;
import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_BOOT_UP;
+import static com.android.server.hdmi.HdmiCecFeatureAction.DELAY_GIVE_AUDIO_STATUS;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.TruthJUnit.assume;
@@ -582,6 +583,9 @@
);
mTestLooper.dispatchAll();
+ mTestLooper.moveTimeForward(DELAY_GIVE_AUDIO_STATUS);
+ mTestLooper.dispatchAll();
+
assertThat(mNativeWrapper.getResultMessages()).contains(
HdmiCecMessageBuilder.buildUserControlPressed(getLogicalAddress(),
getSystemAudioDeviceLogicalAddress(), CEC_KEYCODE_VOLUME_UP));
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/BaseTvToAudioSystemAvbTest.java b/services/tests/servicestests/src/com/android/server/hdmi/BaseTvToAudioSystemAvbTest.java
index 6731403..ec44a91 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/BaseTvToAudioSystemAvbTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/BaseTvToAudioSystemAvbTest.java
@@ -17,6 +17,7 @@
package com.android.server.hdmi;
import static com.android.server.hdmi.HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP;
+import static com.android.server.hdmi.HdmiCecFeatureAction.DELAY_GIVE_AUDIO_STATUS;
import static com.google.common.truth.Truth.assertThat;
@@ -223,6 +224,9 @@
);
mTestLooper.dispatchAll();
+ mTestLooper.moveTimeForward(DELAY_GIVE_AUDIO_STATUS);
+ mTestLooper.dispatchAll();
+
assertThat(mNativeWrapper.getResultMessages()).contains(
HdmiCecMessageBuilder.buildUserControlPressed(getLogicalAddress(),
getSystemAudioDeviceLogicalAddress(), CEC_KEYCODE_VOLUME_UP));
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
index a7e8a00..2d95740 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
@@ -29,6 +29,8 @@
import static com.android.server.hdmi.HdmiControlService.STANDBY_SCREEN_OFF;
import static com.android.server.hdmi.HdmiControlService.WAKE_UP_SCREEN_ON;
import static com.android.server.hdmi.RequestActiveSourceAction.TIMEOUT_WAIT_FOR_LAUNCHERX_API_CALL_MS;
+import static com.android.server.hdmi.RoutingControlAction.TIMEOUT_ROUTING_INFORMATION_MS;
+import static com.android.server.hdmi.RequestSadAction.RETRY_COUNTER_MAX;
import static com.google.common.truth.Truth.assertThat;
@@ -77,6 +79,7 @@
public class HdmiCecLocalDeviceTvTest {
private static final int TIMEOUT_MS = HdmiConfig.TIMEOUT_MS + 1;
private static final int PORT_1 = 1;
+ private static final int PORT_2 = 2;
private static final String[] SADS_NOT_TO_QUERY = new String[]{
HdmiControlManager.CEC_SETTING_NAME_QUERY_SAD_MPEG1,
@@ -215,7 +218,7 @@
.setEarcSupported(false)
.build();
hdmiPortInfos[1] =
- new HdmiPortInfo.Builder(2, HdmiPortInfo.PORT_INPUT, 0x2000)
+ new HdmiPortInfo.Builder(PORT_2, HdmiPortInfo.PORT_INPUT, 0x2000)
.setCecSupported(true)
.setMhlSupported(false)
.setArcSupported(true)
@@ -271,13 +274,12 @@
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated);
// Finish querying SADs
- assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
- mNativeWrapper.clearResultMessages();
- mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
- mTestLooper.dispatchAll();
- assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
- mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
- mTestLooper.dispatchAll();
+ for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) {
+ assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ }
assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated);
mNativeWrapper.clearResultMessages();
@@ -683,18 +685,46 @@
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated);
// Finish querying SADs
- assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
- mNativeWrapper.clearResultMessages();
- mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
- mTestLooper.dispatchAll();
- assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
- mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
- mTestLooper.dispatchAll();
+ for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) {
+ assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ }
assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated);
}
@Test
+ public void handleInitiateArc_arcAlreadyEstablished_noRequestSad() {
+ // Emulate Audio device on port 0x2000 (supports ARC)
+ mNativeWrapper.setPortConnectionStatus(2, true);
+ HdmiCecMessage reportPhysicalAddress =
+ HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
+ ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
+ mNativeWrapper.onCecMessage(reportPhysicalAddress);
+ mTestLooper.dispatchAll();
+
+ assertThat(mHdmiCecLocalDeviceTv.isArcEstablished()).isFalse();
+
+ HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildInitiateArc(
+ ADDR_AUDIO_SYSTEM,
+ ADDR_TV);
+ mNativeWrapper.onCecMessage(requestArcInitiation);
+ mTestLooper.dispatchAll();
+
+ // Finish querying SADs
+ for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) {
+ assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ }
+
+ assertThat(mHdmiCecLocalDeviceTv.isArcEstablished()).isTrue();
+ }
+
+ @Test
public void handleTerminateArc_noAudioDevice() {
HdmiCecMessage terminateArc = HdmiCecMessageBuilder.buildTerminateArc(
ADDR_AUDIO_SYSTEM,
@@ -968,13 +998,12 @@
// <Report ARC Initiated> should only be sent after SAD querying is done
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated);
// Finish querying SADs
- assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
- mNativeWrapper.clearResultMessages();
- mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
- mTestLooper.dispatchAll();
- assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
- mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
- mTestLooper.dispatchAll();
+ for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) {
+ assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ }
assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated);
mNativeWrapper.clearResultMessages();
@@ -1169,13 +1198,12 @@
mTestLooper.dispatchAll();
// Finish querying SADs
- assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
- mNativeWrapper.clearResultMessages();
- mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
- mTestLooper.dispatchAll();
- assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
- mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
- mTestLooper.dispatchAll();
+ for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) {
+ assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ }
// ARC should be established after RequestSadAction is finished
assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated);
@@ -1325,13 +1353,12 @@
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated);
// Finish querying SADs
- assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
- mNativeWrapper.clearResultMessages();
- mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
- mTestLooper.dispatchAll();
- assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
- mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
- mTestLooper.dispatchAll();
+ for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) {
+ assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ }
assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated);
}
@@ -2021,7 +2048,7 @@
ADDR_TV);
mTestLooper.dispatchAll();
- assertThat(mHdmiCecLocalDeviceTv.getWasActiveSourceSetToConnectedDevice())
+ assertThat(mHdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
.isFalse();
mPowerManager.setInteractive(true);
mTestLooper.dispatchAll();
@@ -2031,14 +2058,14 @@
"HdmiCecLocalDeviceTvTest");
mTestLooper.dispatchAll();
- assertThat(mHdmiCecLocalDeviceTv.getWasActiveSourceSetToConnectedDevice())
+ assertThat(mHdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
.isTrue();
assertThat(mHdmiCecLocalDeviceTv.dispatchMessage(standbyMessage))
.isEqualTo(Constants.HANDLED);
mTestLooper.dispatchAll();
assertThat(mPowerManager.isInteractive()).isFalse();
- assertThat(mHdmiCecLocalDeviceTv.getWasActiveSourceSetToConnectedDevice())
+ assertThat(mHdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
.isFalse();
}
@@ -2051,7 +2078,7 @@
mHdmiCecLocalDeviceTv = new MockTvDevice(mHdmiControlService);
mTestLooper.dispatchAll();
- assertThat(mHdmiCecLocalDeviceTv.getWasActiveSourceSetToConnectedDevice())
+ assertThat(mHdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
.isFalse();
mPowerManager.setInteractive(true);
@@ -2060,7 +2087,7 @@
"HdmiCecLocalDeviceTvTest");
mTestLooper.dispatchAll();
- assertThat(mHdmiCecLocalDeviceTv.getWasActiveSourceSetToConnectedDevice())
+ assertThat(mHdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
.isTrue();
assertThat(mHdmiCecLocalDeviceTv.dispatchMessage(standbyMessage))
.isEqualTo(Constants.HANDLED);
@@ -2076,22 +2103,51 @@
mHdmiCecLocalDeviceTv = new MockTvDevice(mHdmiControlService);
mTestLooper.dispatchAll();
- assertThat(mHdmiCecLocalDeviceTv.getWasActiveSourceSetToConnectedDevice())
+ assertThat(mHdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
.isFalse();
mPowerManager.setInteractive(true);
- assertThat(mHdmiCecLocalDeviceTv.getWasActiveSourceSetToConnectedDevice())
+ assertThat(mHdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
.isFalse();
assertThat(mHdmiCecLocalDeviceTv.dispatchMessage(standbyMessage))
.isEqualTo(Constants.HANDLED);
mTestLooper.dispatchAll();
assertThat(mPowerManager.isInteractive()).isFalse();
- assertThat(mHdmiCecLocalDeviceTv.getWasActiveSourceSetToConnectedDevice())
+ assertThat(mHdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
.isFalse();
}
@Test
+ public void handleStandby_fromNonActiveSource_previousActivePathSetToNonCecDevice_Standby() {
+ HdmiCecLocalDeviceTv hdmiCecLocalDeviceTv = new MockTvDevice(mHdmiControlService);
+ hdmiCecLocalDeviceTv.setDeviceInfo(mHdmiCecLocalDeviceTv.getDeviceInfo());
+ mTestLooper.dispatchAll();
+
+ assertThat(hdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
+ .isFalse();
+ mPowerManager.setInteractive(true);
+ hdmiCecLocalDeviceTv.doManualPortSwitching(PORT_2, null);
+ mTestLooper.dispatchAll();
+
+ // Timeout the action RoutingControlAction such that the active path would be updated.
+ mTestLooper.moveTimeForward(TIMEOUT_ROUTING_INFORMATION_MS);
+ mTestLooper.dispatchAll();
+
+ assertThat(hdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
+ .isTrue();
+ HdmiCecMessage standbyMessage = HdmiCecMessageBuilder.buildStandby(
+ ADDR_PLAYBACK_1, ADDR_TV);
+ assertThat(hdmiCecLocalDeviceTv.dispatchMessage(standbyMessage))
+ .isEqualTo(Constants.HANDLED);
+ mTestLooper.dispatchAll();
+
+ assertThat(mPowerManager.isInteractive()).isTrue();
+ assertThat(hdmiCecLocalDeviceTv.getWasActivePathSetToConnectedDevice())
+ .isTrue();
+ }
+
+ @Test
public void handleReportPhysicalAddress_DeviceDiscoveryActionInProgress_noNewDeviceAction() {
mHdmiControlService.getHdmiCecNetwork().clearDeviceList();
mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_1, SendMessageResult.SUCCESS);
@@ -2189,7 +2245,7 @@
@Override
protected int handleActiveSource(HdmiCecMessage message) {
- setWasActiveSourceSetToConnectedDevice(true);
+ setWasActivePathSetToConnectedDevice(true);
return super.handleActiveSource(message);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java
index f8e465c..4cf2937 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/RequestSadActionTest.java
@@ -18,6 +18,7 @@
import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
+import static com.android.server.hdmi.RequestSadAction.RETRY_COUNTER_MAX;
import static com.google.common.truth.Truth.assertThat;
@@ -144,7 +145,7 @@
}
@Test
- public void noResponse_queryAgainOnce_emptyResult() {
+ public void noResponse_queryAgain_emptyResult() {
RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
mCallback);
action.start();
@@ -154,13 +155,13 @@
HdmiCecMessage expected1 = HdmiCecMessageBuilder.buildRequestShortAudioDescriptor(
mTvLogicalAddress, Constants.ADDR_AUDIO_SYSTEM,
CODECS_TO_QUERY_1.stream().mapToInt(i -> i).toArray());
- assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
- mNativeWrapper.clearResultMessages();
- mTestLooper.moveTimeForward(TIMEOUT_MS);
- mTestLooper.dispatchAll();
- assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
- mTestLooper.moveTimeForward(TIMEOUT_MS);
- mTestLooper.dispatchAll();
+
+ for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) {
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ }
assertThat(mSupportedSads).isNotNull();
assertThat(mSupportedSads.size()).isEqualTo(0);
@@ -507,7 +508,7 @@
}
@Test
- public void invalidMessageLength_queryAgainOnce() {
+ public void invalidMessageLength_queryAgain() {
RequestSadAction action = new RequestSadAction(mHdmiCecLocalDeviceTv, ADDR_AUDIO_SYSTEM,
mCallback);
action.start();
@@ -524,16 +525,13 @@
0x27, 0x20, 0x0A};
HdmiCecMessage response1 = HdmiCecMessageBuilder.buildReportShortAudioDescriptor(
Constants.ADDR_AUDIO_SYSTEM, mTvLogicalAddress, sadsToRespond_1);
- assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
- mNativeWrapper.clearResultMessages();
- action.processCommand(response1);
- mTestLooper.dispatchAll();
- mTestLooper.moveTimeForward(TIMEOUT_MS);
- mTestLooper.dispatchAll();
- assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
- mNativeWrapper.clearResultMessages();
- mTestLooper.moveTimeForward(TIMEOUT_MS);
- mTestLooper.dispatchAll();
+
+ for (int i = 0; i <= RETRY_COUNTER_MAX; ++i) {
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected1);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ }
assertThat(mSupportedSads).isNotNull();
assertThat(mSupportedSads.size()).isEqualTo(0);
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 7912156..e652df5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -34,6 +34,7 @@
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.os.IpcDataCache;
import android.os.PersistableBundle;
import android.os.UserHandle;
import android.os.UserManager;
@@ -100,6 +101,9 @@
@Before
public void setUp() throws Exception {
+ // Disable binder caches in this process.
+ IpcDataCache.disableForTestMode();
+
mOriginalCurrentUserId = ActivityManager.getCurrentUser();
mUserManager = UserManager.get(mContext);
mActivityManager = mContext.getSystemService(ActivityManager.class);
diff --git a/services/tests/servicestests/src/com/android/server/rollback/ApexdRevertLoggerTest.java b/services/tests/servicestests/src/com/android/server/rollback/ApexdRevertLoggerTest.java
new file mode 100644
index 0000000..4aa6d39
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/rollback/ApexdRevertLoggerTest.java
@@ -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.server.rollback;
+
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.same;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public class ApexdRevertLoggerTest {
+
+ private Context mMockContext = mock(Context.class);
+ private PackageManager mMockPm;
+ private PackageInfo mPackageInfo;
+
+ private static final String LOGGING_PARENT_KEY = "android.content.pm.LOGGING_PARENT";
+ private static final int PACKAGE_INFO_FLAGS = PackageManager.MATCH_APEX
+ | PackageManager.GET_META_DATA;
+ private static final List<String> sFailingPackages =
+ List.of("package1", "package2", "package3");
+
+ @Before
+ public void setUp() {
+ mMockPm = mock(PackageManager.class);
+ when(mMockContext.getPackageManager()).thenReturn(mMockPm);
+ PackageInstaller mockPi = mock(PackageInstaller.class);
+ when(mMockPm.getPackageInstaller()).thenReturn(mockPi);
+ PackageInstaller.SessionInfo mockSessionInfo = mock(PackageInstaller.SessionInfo.class);
+ when(mockPi.getSessionInfo(anyInt())).thenReturn(mockSessionInfo);
+ mPackageInfo = new PackageInfo();
+ }
+
+ /**
+ * Ensures that we make the correct Package Manager calls in the case that the failing packages
+ * are correctly configured with parent packages.
+ */
+ @Test
+ public void testApexdLoggingCallsWithParents() throws Exception {
+ for (String failingPackage: sFailingPackages) {
+ PackageInfo packageInfo = new PackageInfo();
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ Bundle bundle = new Bundle();
+ bundle.putString(LOGGING_PARENT_KEY, getParent(failingPackage));
+ applicationInfo.metaData = bundle;
+ packageInfo.applicationInfo = applicationInfo;
+ when(mMockPm.getPackageInfo(same(failingPackage), anyInt())).thenReturn(packageInfo);
+ }
+
+ when(mMockPm.getPackageInfo(anyString(), eq(0))).thenReturn(mPackageInfo);
+ ApexdRevertLogger.logApexdRevert(mMockContext, sFailingPackages, "test_process");
+ for (String failingPackage: sFailingPackages) {
+ verify(mMockPm, times(1)).getPackageInfo(failingPackage, PACKAGE_INFO_FLAGS);
+ verify(mMockPm, times(1)).getPackageInfo(getParent(failingPackage), 0);
+ }
+ }
+
+ /**
+ * Ensures that we don't make any calls to parent packages in the case that packages are not
+ * correctly configured with parent packages.
+ */
+ @Test
+ public void testApexdLoggingCallsWithNoParents() throws Exception {
+ for (String failingPackage: sFailingPackages) {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.applicationInfo = new ApplicationInfo();
+ when(mMockPm.getPackageInfo(same(failingPackage), anyInt())).thenReturn(packageInfo);
+ }
+ when(mMockPm.getPackageInfo(anyString(), eq(0))).thenReturn(mPackageInfo);
+
+ ApexdRevertLogger.logApexdRevert(mMockContext, sFailingPackages, "test_process");
+ verify(mMockPm, times(sFailingPackages.size())).getPackageInfo(anyString(), anyInt());
+ for (String failingPackage: sFailingPackages) {
+ verify(mMockPm, times(1)).getPackageInfo(failingPackage, PACKAGE_INFO_FLAGS);
+ }
+ }
+
+ private String getParent(String packageName) {
+ return packageName + "-parent";
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/rollback/WatchdogRollbackLoggerTest.java b/services/tests/servicestests/src/com/android/server/rollback/WatchdogRollbackLoggerTest.java
index d1c9643..8257168 100644
--- a/services/tests/servicestests/src/com/android/server/rollback/WatchdogRollbackLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/rollback/WatchdogRollbackLoggerTest.java
@@ -20,7 +20,6 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@@ -139,52 +138,4 @@
verify(mMockPm, times(1)).getPackageInfo(
sTestPackageV1.getPackageName(), PACKAGE_INFO_FLAGS);
}
-
- /**
- * Ensures that we make the correct Package Manager calls in the case that the failing packages
- * are correctly configured with parent packages.
- */
- @Test
- public void testApexdLoggingCallsWithParents() throws Exception {
- for (String failingPackage: sFailingPackages) {
- PackageInfo packageInfo = new PackageInfo();
- ApplicationInfo applicationInfo = new ApplicationInfo();
- Bundle bundle = new Bundle();
- bundle.putString(LOGGING_PARENT_KEY, getParent(failingPackage));
- applicationInfo.metaData = bundle;
- packageInfo.applicationInfo = applicationInfo;
- when(mMockPm.getPackageInfo(same(failingPackage), anyInt())).thenReturn(packageInfo);
- }
-
- when(mMockPm.getPackageInfo(anyString(), eq(0))).thenReturn(mPackageInfo);
- WatchdogRollbackLogger.logApexdRevert(mMockContext, sFailingPackages, "test_process");
- for (String failingPackage: sFailingPackages) {
- verify(mMockPm, times(1)).getPackageInfo(failingPackage, PACKAGE_INFO_FLAGS);
- verify(mMockPm, times(1)).getPackageInfo(getParent(failingPackage), 0);
- }
- }
-
- /**
- * Ensures that we don't make any calls to parent packages in the case that packages are not
- * correctly configured with parent packages.
- */
- @Test
- public void testApexdLoggingCallsWithNoParents() throws Exception {
- for (String failingPackage: sFailingPackages) {
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.applicationInfo = new ApplicationInfo();
- when(mMockPm.getPackageInfo(same(failingPackage), anyInt())).thenReturn(packageInfo);
- }
- when(mMockPm.getPackageInfo(anyString(), eq(0))).thenReturn(mPackageInfo);
-
- WatchdogRollbackLogger.logApexdRevert(mMockContext, sFailingPackages, "test_process");
- verify(mMockPm, times(sFailingPackages.size())).getPackageInfo(anyString(), anyInt());
- for (String failingPackage: sFailingPackages) {
- verify(mMockPm, times(1)).getPackageInfo(failingPackage, PACKAGE_INFO_FLAGS);
- }
- }
-
- private String getParent(String packageName) {
- return packageName + "-parent";
- }
}
diff --git a/services/tests/servicestests/utils/com/android/server/testutils/StubTransaction.java b/services/tests/servicestests/utils/com/android/server/testutils/StubTransaction.java
index e27bb4c..b9ece93 100644
--- a/services/tests/servicestests/utils/com/android/server/testutils/StubTransaction.java
+++ b/services/tests/servicestests/utils/com/android/server/testutils/StubTransaction.java
@@ -40,12 +40,19 @@
public class StubTransaction extends SurfaceControl.Transaction {
private HashSet<Runnable> mWindowInfosReportedListeners = new HashSet<>();
+ private HashSet<SurfaceControl.TransactionCommittedListener> mTransactionCommittedListeners =
+ new HashSet<>();
@Override
public void apply() {
for (Runnable listener : mWindowInfosReportedListeners) {
listener.run();
}
+ for (SurfaceControl.TransactionCommittedListener listener
+ : mTransactionCommittedListeners) {
+ listener.onTransactionCommitted();
+ }
+ mTransactionCommittedListeners.clear();
}
@Override
@@ -239,6 +246,9 @@
@Override
public SurfaceControl.Transaction addTransactionCommittedListener(Executor executor,
SurfaceControl.TransactionCommittedListener listener) {
+ SurfaceControl.TransactionCommittedListener listenerInner =
+ () -> executor.execute(listener::onTransactionCommitted);
+ mTransactionCommittedListeners.add(listenerInner);
return this;
}
diff --git a/services/tests/timetests/Android.bp b/services/tests/timetests/Android.bp
index 23ab859..05a1433 100644
--- a/services/tests/timetests/Android.bp
+++ b/services/tests/timetests/Android.bp
@@ -25,3 +25,27 @@
certificate: "platform",
test_suites: ["device-tests"],
}
+
+test_module_config {
+ name: "FrameworksTimeServicesTests_time",
+ base: "FrameworksTimeServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: [
+ "com.android.server.timezonedetector.",
+ "com.android.server.timedetector.",
+ ],
+}
+
+test_module_config {
+ name: "FrameworksTimeServicesTests_server_timedetector",
+ base: "FrameworksTimeServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.timedetector."],
+}
+
+test_module_config {
+ name: "FrameworksTimeServicesTests_server_timezonedetector",
+ base: "FrameworksTimeServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.timezonedetector."],
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java b/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java
index b3ec215..c9d5241 100644
--- a/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java
+++ b/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java
@@ -30,6 +30,7 @@
import androidx.test.InstrumentationRegistry;
+import com.android.server.pm.UserManagerInternal;
import com.android.server.uri.UriGrantsManagerInternal;
import org.junit.After;
@@ -41,6 +42,7 @@
public class UiServiceTestCase {
@Mock protected PackageManagerInternal mPmi;
+ @Mock protected UserManagerInternal mUmi;
@Mock protected UriGrantsManagerInternal mUgmInternal;
protected static final String PKG_N_MR1 = "com.example.n_mr1";
@@ -92,6 +94,8 @@
}
});
+ LocalServices.removeServiceForTest(UserManagerInternal.class);
+ LocalServices.addService(UserManagerInternal.class, mUmi);
LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
when(mUgmInternal.checkGrantUriPermission(
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java b/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
index 7933f7a..1890879 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
@@ -39,6 +39,7 @@
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
+import android.app.KeyguardManager;
import android.app.UiModeManager;
import android.app.WallpaperManager;
import android.content.BroadcastReceiver;
@@ -46,6 +47,7 @@
import android.content.IntentFilter;
import android.hardware.display.ColorDisplayManager;
import android.os.PowerManager;
+import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.ZenDeviceEffects;
import android.testing.TestableContext;
@@ -64,6 +66,9 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
@RunWith(TestParameterInjector.class)
public class DefaultDeviceEffectsApplierTest {
@@ -74,6 +79,7 @@
private DefaultDeviceEffectsApplier mApplier;
@Mock PowerManager mPowerManager;
@Mock ColorDisplayManager mColorDisplayManager;
+ @Mock KeyguardManager mKeyguardManager;
@Mock UiModeManager mUiModeManager;
@Mock WallpaperManager mWallpaperManager;
@@ -83,12 +89,15 @@
mContext = spy(new TestableContext(InstrumentationRegistry.getContext(), null));
mContext.addMockSystemService(PowerManager.class, mPowerManager);
mContext.addMockSystemService(ColorDisplayManager.class, mColorDisplayManager);
+ mContext.addMockSystemService(KeyguardManager.class, mKeyguardManager);
mContext.addMockSystemService(UiModeManager.class, mUiModeManager);
mContext.addMockSystemService(WallpaperManager.class, mWallpaperManager);
when(mWallpaperManager.isWallpaperSupported()).thenReturn(true);
mApplier = new DefaultDeviceEffectsApplier(mContext);
verify(mWallpaperManager).isWallpaperSupported();
+
+ ZenLog.clear();
}
@Test
@@ -110,6 +119,41 @@
}
@Test
+ @EnableFlags(android.app.Flags.FLAG_MODES_API)
+ public void apply_logsToZenLog() {
+ when(mPowerManager.isInteractive()).thenReturn(true);
+ ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ ArgumentCaptor<IntentFilter> intentFilterCaptor =
+ ArgumentCaptor.forClass(IntentFilter.class);
+
+ ZenDeviceEffects effects = new ZenDeviceEffects.Builder()
+ .setShouldDisplayGrayscale(true)
+ .setShouldUseNightMode(true)
+ .build();
+ mApplier.apply(effects, ORIGIN_APP);
+
+ String zenLog = getZenLog();
+ assertThat(zenLog).contains("apply_device_effect: displayGrayscale -> true");
+ assertThat(zenLog).contains("schedule_device_effect: nightMode -> true");
+ assertThat(zenLog).doesNotContain("apply_device_effect: nightMode");
+
+ verify(mContext).registerReceiver(broadcastReceiverCaptor.capture(),
+ intentFilterCaptor.capture(), anyInt());
+ BroadcastReceiver screenOffReceiver = broadcastReceiverCaptor.getValue();
+ screenOffReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF));
+
+ zenLog = getZenLog();
+ assertThat(zenLog).contains("apply_device_effect: nightMode -> true");
+ }
+
+ private static String getZenLog() {
+ StringWriter zenLogWriter = new StringWriter();
+ ZenLog.dump(new PrintWriter(zenLogWriter), "");
+ return zenLogWriter.toString();
+ }
+
+ @Test
public void apply_removesEffects() {
mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
@@ -270,6 +314,22 @@
}
@Test
+ @EnableFlags({android.app.Flags.FLAG_MODES_API, android.app.Flags.FLAG_MODES_UI})
+ public void apply_nightModeWithScreenOnAndKeyguardShowing_appliedImmediately(
+ @TestParameter ZenChangeOrigin origin) {
+
+ when(mPowerManager.isInteractive()).thenReturn(true);
+ when(mKeyguardManager.isKeyguardLocked()).thenReturn(true);
+
+ mApplier.apply(new ZenDeviceEffects.Builder().setShouldUseNightMode(true).build(),
+ origin.value());
+
+ // Effect was applied, and no broadcast receiver was registered.
+ verify(mUiModeManager).setAttentionModeThemeOverlay(eq(MODE_ATTENTION_THEME_OVERLAY_NIGHT));
+ verify(mContext, never()).registerReceiver(any(), any(), anyInt());
+ }
+
+ @Test
@TestParameters({"{origin: ORIGIN_USER_IN_SYSTEMUI}", "{origin: ORIGIN_USER_IN_APP}",
"{origin: ORIGIN_INIT}", "{origin: ORIGIN_INIT_USER}"})
public void apply_nightModeWithScreenOn_appliedImmediatelyBasedOnOrigin(
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index fb82b872c..48bc9d7 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -888,7 +888,7 @@
return true;
});
- mockServiceInfoWithMetaData(List.of(cn), service, pm, new ArrayMap<>());
+ mockServiceInfoWithMetaData(List.of(cn), service, new ArrayMap<>());
service.addApprovedList("a", 0, true);
service.reregisterService(cn, 0);
@@ -919,7 +919,7 @@
return true;
});
- mockServiceInfoWithMetaData(List.of(cn), service, pm, new ArrayMap<>());
+ mockServiceInfoWithMetaData(List.of(cn), service, new ArrayMap<>());
service.addApprovedList("a", 0, false);
service.reregisterService(cn, 0);
@@ -950,7 +950,7 @@
return true;
});
- mockServiceInfoWithMetaData(List.of(cn), service, pm, new ArrayMap<>());
+ mockServiceInfoWithMetaData(List.of(cn), service, new ArrayMap<>());
service.addApprovedList("a/a", 0, true);
service.reregisterService(cn, 0);
@@ -981,7 +981,7 @@
return true;
});
- mockServiceInfoWithMetaData(List.of(cn), service, pm, new ArrayMap<>());
+ mockServiceInfoWithMetaData(List.of(cn), service, new ArrayMap<>());
service.addApprovedList("a/a", 0, false);
service.reregisterService(cn, 0);
@@ -1211,64 +1211,6 @@
}
@Test
- public void testUpgradeAppNoIntentFilterNoRebind() throws Exception {
- Context context = spy(getContext());
- doReturn(true).when(context).bindServiceAsUser(any(), any(), anyInt(), any());
-
- ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles,
- mIpm, APPROVAL_BY_COMPONENT);
-
- List<String> packages = new ArrayList<>();
- packages.add("package");
- addExpectedServices(service, packages, 0);
-
- final ComponentName unapprovedComponent = ComponentName.unflattenFromString("package/C1");
- final ComponentName approvedComponent = ComponentName.unflattenFromString("package/C2");
-
- // Both components are approved initially
- mExpectedPrimaryComponentNames.clear();
- mExpectedPrimaryPackages.clear();
- mExpectedPrimaryComponentNames.put(0, "package/C1:package/C2");
- mExpectedSecondaryComponentNames.clear();
- mExpectedSecondaryPackages.clear();
-
- loadXml(service);
-
- //Component package/C1 loses serviceInterface intent filter
- ManagedServices.Config config = service.getConfig();
- when(mPm.queryIntentServicesAsUser(any(), anyInt(), anyInt())).
- thenAnswer(new Answer<List<ResolveInfo>>() {
- @Override
- public List<ResolveInfo> answer(InvocationOnMock invocationOnMock)
- throws Throwable {
- Object[] args = invocationOnMock.getArguments();
- Intent invocationIntent = (Intent) args[0];
- if (invocationIntent != null) {
- if (invocationIntent.getAction().equals(config.serviceInterface)
- && packages.contains(invocationIntent.getPackage())) {
- List<ResolveInfo> dummyServices = new ArrayList<>();
- ResolveInfo resolveInfo = new ResolveInfo();
- ServiceInfo serviceInfo = new ServiceInfo();
- serviceInfo.packageName = invocationIntent.getPackage();
- serviceInfo.name = approvedComponent.getClassName();
- serviceInfo.permission = service.getConfig().bindPermission;
- resolveInfo.serviceInfo = serviceInfo;
- dummyServices.add(resolveInfo);
- return dummyServices;
- }
- }
- return new ArrayList<>();
- }
- });
-
- // Trigger package update
- service.onPackagesChanged(false, new String[]{"package"}, new int[]{0});
-
- assertFalse(service.isComponentEnabledForCurrentProfiles(unapprovedComponent));
- assertTrue(service.isComponentEnabledForCurrentProfiles(approvedComponent));
- }
-
- @Test
public void testSetPackageOrComponentEnabled() throws Exception {
for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
@@ -1542,6 +1484,7 @@
assertTrue(componentsToUnbind.get(0).contains(ComponentName.unflattenFromString("c/c")));
}
+ @SuppressWarnings("GuardedBy")
@Test
public void populateComponentsToBind() {
ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm,
@@ -1565,7 +1508,8 @@
SparseArray<Set<ComponentName>> componentsToBind = new SparseArray<>();
- service.populateComponentsToBind(componentsToBind, users, approvedComponentsByUser);
+ service.populateComponentsToBind(componentsToBind, users, approvedComponentsByUser,
+ /* isVisibleBackgroundUser= */ false);
assertEquals(2, componentsToBind.size());
assertEquals(1, componentsToBind.get(0).size());
@@ -1575,6 +1519,33 @@
assertTrue(componentsToBind.get(10).contains(ComponentName.unflattenFromString("c/c")));
}
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void populateComponentsToBind_isVisibleBackgroundUser_addComponentsToBindButNotAddToEnabledComponent() {
+ ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm,
+ APPROVAL_BY_COMPONENT);
+
+ SparseArray<ArraySet<ComponentName>> approvedComponentsByUser = new SparseArray<>();
+ ArraySet<ComponentName> allowed = new ArraySet<>();
+ allowed.add(ComponentName.unflattenFromString("pkg1/cmp1"));
+ approvedComponentsByUser.put(11, allowed);
+ IntArray users = new IntArray();
+ users.add(11);
+
+ SparseArray<Set<ComponentName>> componentsToBind = new SparseArray<>();
+
+ service.populateComponentsToBind(componentsToBind, users, approvedComponentsByUser,
+ /* isVisibleBackgroundUser= */ true);
+
+ assertEquals(1, componentsToBind.size());
+ assertEquals(1, componentsToBind.get(11).size());
+ assertTrue(componentsToBind.get(11).contains(ComponentName.unflattenFromString(
+ "pkg1/cmp1")));
+ assertThat(service.isComponentEnabledForCurrentProfiles(
+ new ComponentName("pkg1", "cmp1"))).isFalse();
+ assertThat(service.isComponentEnabledForPackage("pkg1")).isFalse();
+ }
+
@Test
public void testOnNullBinding() throws Exception {
Context context = mock(Context.class);
@@ -1973,7 +1944,7 @@
metaDataAutobindAllow.putBoolean(META_DATA_DEFAULT_AUTOBIND, true);
metaDatas.put(cn_allowed, metaDataAutobindAllow);
- mockServiceInfoWithMetaData(componentNames, service, pm, metaDatas);
+ mockServiceInfoWithMetaData(componentNames, service, metaDatas);
service.addApprovedList(cn_allowed.flattenToString(), 0, true);
service.addApprovedList(cn_disallowed.flattenToString(), 0, true);
@@ -2018,7 +1989,7 @@
metaDataAutobindDisallow.putBoolean(META_DATA_DEFAULT_AUTOBIND, false);
metaDatas.put(cn_disallowed, metaDataAutobindDisallow);
- mockServiceInfoWithMetaData(componentNames, service, pm, metaDatas);
+ mockServiceInfoWithMetaData(componentNames, service, metaDatas);
service.addApprovedList(cn_disallowed.flattenToString(), 0, true);
@@ -2057,7 +2028,7 @@
metaDataAutobindDisallow.putBoolean(META_DATA_DEFAULT_AUTOBIND, false);
metaDatas.put(cn_disallowed, metaDataAutobindDisallow);
- mockServiceInfoWithMetaData(componentNames, service, pm, metaDatas);
+ mockServiceInfoWithMetaData(componentNames, service, metaDatas);
service.addApprovedList(cn_disallowed.flattenToString(), 0, true);
@@ -2128,8 +2099,8 @@
}
private void mockServiceInfoWithMetaData(List<ComponentName> componentNames,
- ManagedServices service, PackageManager packageManager,
- ArrayMap<ComponentName, Bundle> metaDatas) throws RemoteException {
+ ManagedServices service, ArrayMap<ComponentName, Bundle> metaDatas)
+ throws RemoteException {
when(mIpm.getServiceInfo(any(), anyLong(), anyInt())).thenAnswer(
(Answer<ServiceInfo>) invocation -> {
ComponentName invocationCn = invocation.getArgument(0);
@@ -2144,39 +2115,6 @@
return null;
}
);
-
- // add components to queryIntentServicesAsUser response
- final List<String> packages = new ArrayList<>();
- for (ComponentName cn: componentNames) {
- packages.add(cn.getPackageName());
- }
- ManagedServices.Config config = service.getConfig();
- when(packageManager.queryIntentServicesAsUser(any(), anyInt(), anyInt())).
- thenAnswer(new Answer<List<ResolveInfo>>() {
- @Override
- public List<ResolveInfo> answer(InvocationOnMock invocationOnMock)
- throws Throwable {
- Object[] args = invocationOnMock.getArguments();
- Intent invocationIntent = (Intent) args[0];
- if (invocationIntent != null) {
- if (invocationIntent.getAction().equals(config.serviceInterface)
- && packages.contains(invocationIntent.getPackage())) {
- List<ResolveInfo> dummyServices = new ArrayList<>();
- for (ComponentName cn: componentNames) {
- ResolveInfo resolveInfo = new ResolveInfo();
- ServiceInfo serviceInfo = new ServiceInfo();
- serviceInfo.packageName = invocationIntent.getPackage();
- serviceInfo.name = cn.getClassName();
- serviceInfo.permission = service.getConfig().bindPermission;
- resolveInfo.serviceInfo = serviceInfo;
- dummyServices.add(resolveInfo);
- }
- return dummyServices;
- }
- }
- return new ArrayList<>();
- }
- });
}
private void resetComponentsAndPackages() {
diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp
index 604869c..289f8a9 100644
--- a/services/tests/wmtests/Android.bp
+++ b/services/tests/wmtests/Android.bp
@@ -109,3 +109,35 @@
":OverlayTestApp",
],
}
+
+test_module_config {
+ name: "WmTests_server_policy_Presubmit",
+ base: "WmTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.policy."],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
+
+test_module_config {
+ name: "WmTests_server_policy",
+ base: "WmTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.policy."],
+}
+
+test_module_config {
+ name: "WmTests_wm_utils_Presubmit",
+ base: "WmTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.wm.utils"],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
diff --git a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
index 07934ea..536dcfb 100644
--- a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
@@ -42,7 +42,6 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.clearInvocations;
import android.app.ActivityManager;
import android.app.AppOpsManager;
@@ -135,15 +134,13 @@
doNothing().when(mPhoneWindowManager).initializeHdmiState();
final boolean[] isScreenTurnedOff = { false };
final DisplayPolicy displayPolicy = mock(DisplayPolicy.class);
- doAnswer(invocation -> isScreenTurnedOff[0] = true).when(displayPolicy).screenTurnedOff();
+ doAnswer(invocation -> isScreenTurnedOff[0] = true).when(displayPolicy).screenTurnedOff(
+ anyBoolean());
doAnswer(invocation -> !isScreenTurnedOff[0]).when(displayPolicy).isScreenOnEarly();
doAnswer(invocation -> !isScreenTurnedOff[0]).when(displayPolicy).isScreenOnFully();
mPhoneWindowManager.mDefaultDisplayPolicy = displayPolicy;
mPhoneWindowManager.mDefaultDisplayRotation = mock(DisplayRotation.class);
- final ActivityTaskManagerInternal.SleepTokenAcquirer tokenAcquirer =
- mock(ActivityTaskManagerInternal.SleepTokenAcquirer.class);
- doReturn(tokenAcquirer).when(mAtmInternal).createSleepTokenAcquirer(anyString());
final PowerManager pm = mock(PowerManager.class);
doReturn(true).when(pm).isInteractive();
doReturn(pm).when(mContext).getSystemService(eq(Context.POWER_SERVICE));
@@ -155,9 +152,8 @@
assertThat(mPhoneWindowManager.mIsGoingToSleepDefaultDisplay).isFalse();
// Skip sleep-token for non-sleep-screen-off.
- clearInvocations(tokenAcquirer);
mPhoneWindowManager.screenTurnedOff(DEFAULT_DISPLAY, true /* isSwappingDisplay */);
- verify(tokenAcquirer, never()).acquire(anyInt());
+ verify(displayPolicy).screenTurnedOff(false /* acquireSleepToken */);
assertThat(isScreenTurnedOff[0]).isTrue();
// Apply sleep-token for sleep-screen-off.
@@ -165,21 +161,10 @@
mPhoneWindowManager.startedGoingToSleep(DEFAULT_DISPLAY, 0 /* reason */);
assertThat(mPhoneWindowManager.mIsGoingToSleepDefaultDisplay).isTrue();
mPhoneWindowManager.screenTurnedOff(DEFAULT_DISPLAY, true /* isSwappingDisplay */);
- verify(tokenAcquirer).acquire(eq(DEFAULT_DISPLAY));
+ verify(displayPolicy).screenTurnedOff(true /* acquireSleepToken */);
mPhoneWindowManager.finishedGoingToSleep(DEFAULT_DISPLAY, 0 /* reason */);
assertThat(mPhoneWindowManager.mIsGoingToSleepDefaultDisplay).isFalse();
-
- // Simulate unexpected reversed order: screenTurnedOff -> startedGoingToSleep. The sleep
- // token can still be acquired.
- isScreenTurnedOff[0] = false;
- clearInvocations(tokenAcquirer);
- mPhoneWindowManager.screenTurnedOff(DEFAULT_DISPLAY, true /* isSwappingDisplay */);
- verify(tokenAcquirer, never()).acquire(anyInt());
- assertThat(displayPolicy.isScreenOnEarly()).isFalse();
- assertThat(displayPolicy.isScreenOnFully()).isFalse();
- mPhoneWindowManager.startedGoingToSleep(DEFAULT_DISPLAY, 0 /* reason */);
- verify(tokenAcquirer).acquire(eq(DEFAULT_DISPLAY));
}
@Test
@@ -188,7 +173,7 @@
.FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED);
int[] outAppOp = new int[1];
assertEquals(ADD_OKAY, mPhoneWindowManager.checkAddPermission(TYPE_WALLPAPER,
- /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp));
+ /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp, DEFAULT_DISPLAY));
assertThat(outAppOp[0]).isEqualTo(AppOpsManager.OP_NONE);
}
@@ -198,7 +183,7 @@
.FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED);
int[] outAppOp = new int[1];
assertEquals(ADD_OKAY, mPhoneWindowManager.checkAddPermission(TYPE_ACCESSIBILITY_OVERLAY,
- /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp));
+ /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp, DEFAULT_DISPLAY));
assertThat(outAppOp[0]).isEqualTo(AppOpsManager.OP_CREATE_ACCESSIBILITY_OVERLAY);
}
@@ -208,7 +193,7 @@
.FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED);
int[] outAppOp = new int[1];
assertEquals(ADD_OKAY, mPhoneWindowManager.checkAddPermission(TYPE_ACCESSIBILITY_OVERLAY,
- /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp));
+ /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp, DEFAULT_DISPLAY));
assertThat(outAppOp[0]).isEqualTo(AppOpsManager.OP_NONE);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 1e035da..e2e76d6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -3231,7 +3231,7 @@
mDisplayContent.mOpeningApps.remove(activity);
mDisplayContent.mClosingApps.remove(activity);
activity.commitVisibility(false /* visible */, false /* performLayout */);
- mDisplayContent.getDisplayPolicy().screenTurnedOff();
+ mDisplayContent.getDisplayPolicy().screenTurnedOff(false /* acquireSleepToken */);
final KeyguardController controller = mSupervisor.getKeyguardController();
doReturn(true).when(controller).isKeyguardGoingAway(anyInt());
activity.setVisibility(true);
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 4f94704..c706d52 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -1047,6 +1047,7 @@
info.packageName = packageName;
WindowProcessController wpc = new WindowProcessController(
mAtm, info, packageName, 0, userId, null, mMockListener);
+ mAtm.mInternal.preBindApplication(wpc, info);
wpc.setThread(mock(IApplicationThread.class));
return wpc;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 0c1fbf3..c294bc6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -94,6 +94,7 @@
public void setUp() throws Exception {
assumeFalse(WindowManagerService.sEnableShellTransitions);
mAppTransitionController = new AppTransitionController(mWm, mDisplayContent);
+ mWm.mAnimator.ready();
}
@Test
@@ -855,7 +856,7 @@
// Prepare and start transition.
prepareAndTriggerAppTransition(activity, null /* closingActivity */, taskFragment);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
// Animation run by the remote handler.
assertTrue(remoteAnimationRunner.isAnimationStarted());
@@ -886,7 +887,7 @@
// Prepare and start transition.
prepareAndTriggerAppTransition(openingActivity, closingActivity,
null /* changingTaskFragment */);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
// Animation is not run by the remote handler because the activity is filling the Task.
assertFalse(remoteAnimationRunner.isAnimationStarted());
@@ -921,7 +922,7 @@
// Prepare and start transition.
prepareAndTriggerAppTransition(openingActivity, closingActivity,
null /* changingTaskFragment */);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
// Animation run by the remote handler.
assertTrue(remoteAnimationRunner.isAnimationStarted());
@@ -946,7 +947,7 @@
// Prepare and start transition.
prepareAndTriggerAppTransition(openingActivity, closingActivity, taskFragment);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
// Animation run by the remote handler.
assertTrue(remoteAnimationRunner.isAnimationStarted());
@@ -973,7 +974,7 @@
// Prepare and start transition.
prepareAndTriggerAppTransition(openingActivity, closingActivity, taskFragment1);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
// Animation run by the remote handler.
assertTrue(remoteAnimationRunner.isAnimationStarted());
@@ -997,7 +998,7 @@
// Prepare and start transition.
prepareAndTriggerAppTransition(openingActivity, closingActivity, taskFragment);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
// Animation not run by the remote handler.
assertFalse(remoteAnimationRunner.isAnimationStarted());
@@ -1024,7 +1025,7 @@
// Prepare and start transition.
prepareAndTriggerAppTransition(openingActivity, closingActivity, taskFragment);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
// Animation should not run by the remote handler when there are non-embedded activities of
// different UID.
@@ -1051,7 +1052,7 @@
// Prepare and start transition.
prepareAndTriggerAppTransition(activity, null /* closingActivity */, taskFragment);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
// Animation should not run by the remote handler when there is wallpaper in the transition.
assertFalse(remoteAnimationRunner.isAnimationStarted());
@@ -1085,7 +1086,7 @@
// Prepare and start transition.
prepareAndTriggerAppTransition(activity1, null /* closingActivity */, taskFragment);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
// The animation will be animated remotely by client and all activities are input disabled
// for untrusted animation.
@@ -1136,7 +1137,7 @@
// Prepare and start transition.
prepareAndTriggerAppTransition(activity, null /* closingActivity */, taskFragment);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
// The animation will be animated remotely by client and all activities are input disabled
// for untrusted animation.
@@ -1178,7 +1179,7 @@
// Prepare and start transition.
prepareAndTriggerAppTransition(activity, null /* closingActivity */, taskFragment);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
// The animation will be animated remotely by client, but input should not be dropped for
// fully trusted.
@@ -1302,4 +1303,4 @@
doReturn(mock(RemoteAnimationTarget.class)).when(activity).createRemoteAnimationTarget(
any());
}
-}
\ No newline at end of file
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
index 44837d7..20dcdde 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -110,6 +110,7 @@
mWindowManagerInternal = mock(WindowManagerInternal.class);
LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
mBackAnimationAdapter = mock(BackAnimationAdapter.class);
+ doReturn(true).when(mBackAnimationAdapter).isAnimatable(anyInt());
mNavigationMonitor = mock(BackNavigationController.NavigationMonitor.class);
mRootHomeTask = initHomeActivity();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index caeb41c..f32a234 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -284,11 +284,11 @@
final DisplayPolicy policy = mDisplayContent.getDisplayPolicy();
policy.addWindowLw(mNotificationShadeWindow, mNotificationShadeWindow.mAttrs);
- policy.screenTurnedOff();
+ policy.screenTurnedOff(false /* acquireSleepToken */);
policy.setAwake(false);
policy.screenTurningOn(null /* screenOnListener */);
assertTrue(wpc.isShowingUiWhileDozing());
- policy.screenTurnedOff();
+ policy.screenTurnedOff(false /* acquireSleepToken */);
assertFalse(wpc.isShowingUiWhileDozing());
policy.screenTurningOn(null /* screenOnListener */);
@@ -393,7 +393,7 @@
info.logicalWidth, info.logicalHeight).mConfigFrame);
// If screen is not fully turned on, then the cache should be preserved.
- displayPolicy.screenTurnedOff();
+ displayPolicy.screenTurnedOff(false /* acquireSleepToken */);
final TransitionController transitionController = mDisplayContent.mTransitionController;
spyOn(transitionController);
doReturn(true).when(transitionController).isCollecting();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index 57839e2..ffe3893 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -244,6 +244,19 @@
mWm.clearForcedDisplaySize(mSecondaryDisplay.getDisplayId());
assertEquals(mSecondaryDisplay.mInitialDisplayWidth, mSecondaryDisplay.mBaseDisplayWidth);
assertEquals(mSecondaryDisplay.mInitialDisplayHeight, mSecondaryDisplay.mBaseDisplayHeight);
+
+ // Forced size can be cleared even if the initial display size is smaller than max width.
+ final int maxWidth = mSecondaryDisplay.mInitialDisplayWidth - 20;
+ mSecondaryDisplay.setMaxUiWidth(maxWidth);
+ assertEquals(maxWidth, mSecondaryDisplay.mBaseDisplayWidth);
+ mSecondaryDisplay.setForcedSize(maxWidth - 10, maxWidth + 10);
+ assertNotEquals(maxWidth, mSecondaryDisplay.mBaseDisplayHeight);
+ assertTrue(mSecondaryDisplay.mIsSizeForced);
+
+ mWm.clearForcedDisplaySize(mSecondaryDisplay.mDisplayId);
+ assertFalse(mSecondaryDisplay.mIsSizeForced);
+ assertEquals(maxWidth, mSecondaryDisplay.mBaseDisplayWidth);
+ assertEquals(0, mSettingsProvider.getSettings(originalInfo).mForcedWidth);
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java
index ea175a5..f70dceb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java
@@ -51,6 +51,7 @@
public void setUp() throws Exception {
mImeProvider = mDisplayContent.getInsetsStateController().getImeSourceProvider();
mImeProvider.getSource().setVisible(true);
+ mWm.mAnimator.ready();
}
@Test
@@ -151,8 +152,8 @@
assertFalse(mImeProvider.isScheduledAndReadyToShowIme());
assertFalse(mImeProvider.isImeShowing());
- // Starting the afterPrepareSurfacesRunnable picks up the show scheduled above.
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ // Waiting for the afterPrepareSurfacesRunnable picks up the show scheduled above.
+ waitUntilWindowAnimatorIdle();
// No longer scheduled as it was already shown.
assertFalse(mImeProvider.isScheduledAndReadyToShowIme());
assertTrue(mImeProvider.isImeShowing());
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
index 6190807..e8d089c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
@@ -187,8 +187,8 @@
assertEquals(mProvider.getControlTarget(), target);
assertNull(mProvider.getLeash(target));
- // After surface transactions are applied, the leash is ready for dispatching.
- mProvider.onSurfaceTransactionApplied();
+ // Set the leash to be ready for dispatching.
+ mProvider.mIsLeashReadyForDispatching = true;
assertNotNull(mProvider.getLeash(target));
// We do have fake control for the fake control target, but that has no leash.
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index 964264d..d0d7c06 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -388,6 +388,7 @@
mDisplayContent.getInsetsPolicy().updateBarControlTarget(app);
mDisplayContent.getInsetsPolicy().showTransient(statusBars(),
true /* isGestureOnSystemBar */);
+ mWm.mAnimator.ready();
waitUntilWindowAnimatorIdle();
assertTrue(mDisplayContent.getInsetsPolicy().isTransient(statusBars()));
diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index 6f7d0dc..c5cbedb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -110,6 +110,7 @@
runWithScissors(mWm.mH, () -> mHandler = new TestHandler(null, mClock), 0);
mController = new RemoteAnimationController(mWm, mDisplayContent, mAdapter,
mHandler, false /*isActivityEmbedding*/);
+ mWm.mAnimator.ready();
}
private WindowState createAppOverlayWindow() {
@@ -133,7 +134,7 @@
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
@@ -165,7 +166,7 @@
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
@@ -287,7 +288,7 @@
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
@@ -333,7 +334,7 @@
task.applyAnimationUnchecked(null /* lp */, true /* enter */, TRANSIT_OLD_TASK_OPEN,
false /* isVoiceInteraction */, null /* sources */);
mController.goodToGo(TRANSIT_OLD_TASK_OPEN);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
try {
@@ -360,7 +361,7 @@
((AnimationAdapter) record.mThumbnailAdapter).startAnimation(mMockThumbnailLeash,
mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION, mThumbnailFinishedCallback);
mController.goodToGo(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
@@ -414,7 +415,7 @@
((AnimationAdapter) record.mThumbnailAdapter).startAnimation(mMockThumbnailLeash,
mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION, mThumbnailFinishedCallback);
mController.goodToGo(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
@@ -468,7 +469,7 @@
((AnimationAdapter) record.mThumbnailAdapter).startAnimation(mMockThumbnailLeash,
mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION, mThumbnailFinishedCallback);
mController.goodToGo(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
@@ -523,7 +524,7 @@
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
@@ -556,7 +557,7 @@
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
@@ -592,7 +593,7 @@
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo(TRANSIT_OLD_KEYGUARD_GOING_AWAY);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
@@ -642,7 +643,7 @@
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo(TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
@@ -742,7 +743,7 @@
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo(transit);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ waitUntilWindowAnimatorIdle();
return adapter;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
index 9981a4d..9967cce 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
@@ -36,7 +36,6 @@
import android.view.SurfaceControl;
import android.view.SurfaceControl.Builder;
import android.view.SurfaceControl.Transaction;
-import android.view.SurfaceSession;
import androidx.test.filters.SmallTest;
@@ -69,7 +68,6 @@
@Mock AnimationAdapter mSpec2;
@Mock Transaction mTransaction;
- private SurfaceSession mSession = new SurfaceSession();
private MyAnimatable mAnimatable;
private MyAnimatable mAnimatable2;
private DeferFinishAnimatable mDeferFinishAnimatable;
@@ -78,9 +76,9 @@
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mAnimatable = new MyAnimatable(mWm, mSession, mTransaction);
- mAnimatable2 = new MyAnimatable(mWm, mSession, mTransaction);
- mDeferFinishAnimatable = new DeferFinishAnimatable(mWm, mSession, mTransaction);
+ mAnimatable = new MyAnimatable(mWm, mTransaction);
+ mAnimatable2 = new MyAnimatable(mWm, mTransaction);
+ mDeferFinishAnimatable = new DeferFinishAnimatable(mWm, mTransaction);
}
@After
@@ -88,8 +86,6 @@
mAnimatable = null;
mAnimatable2 = null;
mDeferFinishAnimatable = null;
- mSession.kill();
- mSession = null;
}
@Test
@@ -313,7 +309,6 @@
private static class MyAnimatable implements Animatable {
- private final SurfaceSession mSession;
private final Transaction mTransaction;
final SurfaceControl mParent;
final SurfaceControl mSurface;
@@ -322,13 +317,12 @@
boolean mFinishedCallbackCalled;
@AnimationType int mFinishedAnimationType;
- MyAnimatable(WindowManagerService wm, SurfaceSession session, Transaction transaction) {
- mSession = session;
+ MyAnimatable(WindowManagerService wm, Transaction transaction) {
mTransaction = transaction;
- mParent = wm.makeSurfaceBuilder(mSession)
+ mParent = wm.makeSurfaceBuilder()
.setName("test surface parent")
.build();
- mSurface = wm.makeSurfaceBuilder(mSession)
+ mSurface = wm.makeSurfaceBuilder()
.setName("test surface")
.build();
mFinishedCallbackCalled = false;
@@ -360,7 +354,7 @@
@Override
public Builder makeAnimationLeash() {
- return new Builder(mSession) {
+ return new Builder() {
@Override
public SurfaceControl build() {
@@ -406,9 +400,8 @@
Runnable mEndDeferFinishCallback;
- DeferFinishAnimatable(WindowManagerService wm, SurfaceSession session,
- Transaction transaction) {
- super(wm, session, transaction);
+ DeferFinishAnimatable(WindowManagerService wm, Transaction transaction) {
+ super(wm, transaction);
}
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 1e39f0b..71cfbfd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -394,7 +394,7 @@
mWmService = WindowManagerService.main(
mContext, mImService, false, wmPolicy, mAtmService,
testDisplayWindowSettingsProvider, StubTransaction::new,
- (unused) -> new MockSurfaceControlBuilder());
+ MockSurfaceControlBuilder::new);
spyOn(mWmService);
spyOn(mWmService.mRoot);
// Invoked during {@link ActivityStack} creation.
@@ -571,7 +571,7 @@
// This makes sure all previous messages in the handler are fully processed vs. just popping
// them from the message queue.
final AtomicBoolean currentMessagesProcessed = new AtomicBoolean(false);
- wm.mAnimator.getChoreographer().postFrameCallback(time -> {
+ wm.mAnimator.addAfterPrepareSurfacesRunnable(() -> {
synchronized (currentMessagesProcessed) {
currentMessagesProcessed.set(true);
currentMessagesProcessed.notifyAll();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index a71b81e..0cd036f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -2135,8 +2135,8 @@
private static void setupMockParent(TaskFragment taskFragment, Task mockParent) {
doReturn(mockParent).when(taskFragment).getTask();
doReturn(new TaskFragmentParentInfo(
- new Configuration(), DEFAULT_DISPLAY, true, true, null /* decorSurface */))
- .when(mockParent).getTaskFragmentParentInfo();
+ new Configuration(), DEFAULT_DISPLAY, mockParent.mTaskId, true, true,
+ null /* decorSurface */)).when(mockParent).getTaskFragmentParentInfo();
// Task needs to be visible
mockParent.lastActiveTime = 100;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index cc1805a..fd959b9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -242,7 +242,7 @@
final Rect relStartBounds = new Rect(mTaskFragment.getRelativeEmbeddedBounds());
final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
- displayPolicy.screenTurnedOff();
+ displayPolicy.screenTurnedOff(false /* acquireSleepToken */);
assertFalse(mTaskFragment.okToAnimate());
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index d62c626..eebb487 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -60,7 +60,7 @@
@Override
public int checkAddPermission(int type, boolean isRoundedCornerOverlay, String packageName,
- int[] outAppOp) {
+ int[] outAppOp, int displayId) {
return 0;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 7320c0b..52a80b0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -2005,10 +2005,10 @@
@DisableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testOverrideAnimationOptionsToInfoIfNecessary_disableAnimOptionsPerChange() {
- ActivityRecord r = initializeOverrideAnimationOptionsTest();
+ initializeOverrideAnimationOptionsTest();
TransitionInfo.AnimationOptions options = TransitionInfo.AnimationOptions
.makeCommonAnimOptions("testPackage");
- mTransition.setOverrideAnimation(options, r, null /* startCallback */,
+ mTransition.setOverrideAnimation(options, null /* startCallback */,
null /* finishCallback */);
mTransition.overrideAnimationOptionsToInfoIfNecessary(mInfo);
@@ -2019,10 +2019,10 @@
@EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testOverrideAnimationOptionsToInfoIfNecessary_fromStyleAnimOptions() {
- ActivityRecord r = initializeOverrideAnimationOptionsTest();
+ initializeOverrideAnimationOptionsTest();
TransitionInfo.AnimationOptions options = TransitionInfo.AnimationOptions
.makeCommonAnimOptions("testPackage");
- mTransition.setOverrideAnimation(options, r, null /* startCallback */,
+ mTransition.setOverrideAnimation(options, null /* startCallback */,
null /* finishCallback */);
mTransition.overrideAnimationOptionsToInfoIfNecessary(mInfo);
@@ -2045,10 +2045,10 @@
@EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testOverrideAnimationOptionsToInfoIfNecessary_sceneAnimOptions() {
- ActivityRecord r = initializeOverrideAnimationOptionsTest();
+ initializeOverrideAnimationOptionsTest();
TransitionInfo.AnimationOptions options = TransitionInfo.AnimationOptions
.makeSceneTransitionAnimOptions();
- mTransition.setOverrideAnimation(options, r, null /* startCallback */,
+ mTransition.setOverrideAnimation(options, null /* startCallback */,
null /* finishCallback */);
mTransition.overrideAnimationOptionsToInfoIfNecessary(mInfo);
@@ -2071,10 +2071,10 @@
@EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testOverrideAnimationOptionsToInfoIfNecessary_crossProfileAnimOptions() {
- ActivityRecord r = initializeOverrideAnimationOptionsTest();
+ initializeOverrideAnimationOptionsTest();
TransitionInfo.AnimationOptions options = TransitionInfo.AnimationOptions
.makeCrossProfileAnimOptions();
- mTransition.setOverrideAnimation(options, r, null /* startCallback */,
+ mTransition.setOverrideAnimation(options, null /* startCallback */,
null /* finishCallback */);
final TransitionInfo.Change displayChange = mInfo.getChanges().get(0);
@@ -2099,13 +2099,13 @@
@EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testOverrideAnimationOptionsToInfoIfNecessary_customAnimOptions() {
- ActivityRecord r = initializeOverrideAnimationOptionsTest();
+ initializeOverrideAnimationOptionsTest();
TransitionInfo.AnimationOptions options = TransitionInfo.AnimationOptions
.makeCustomAnimOptions("testPackage", Resources.ID_NULL,
TransitionInfo.AnimationOptions.DEFAULT_ANIMATION_RESOURCES_ID,
TransitionInfo.AnimationOptions.DEFAULT_ANIMATION_RESOURCES_ID,
Color.GREEN, false /* overrideTaskTransition */);
- mTransition.setOverrideAnimation(options, r, null /* startCallback */,
+ mTransition.setOverrideAnimation(options, null /* startCallback */,
null /* finishCallback */);
mTransition.overrideAnimationOptionsToInfoIfNecessary(mInfo);
@@ -2132,7 +2132,7 @@
@EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testOverrideAnimationOptionsToInfoIfNecessary_haveTaskFragmentAnimParams() {
- ActivityRecord r = initializeOverrideAnimationOptionsTest();
+ initializeOverrideAnimationOptionsTest();
final TaskFragment embeddedTf = mTransition.mTargets.get(2).mContainer.asTaskFragment();
embeddedTf.setAnimationParams(new TaskFragmentAnimationParams.Builder()
@@ -2145,7 +2145,7 @@
TransitionInfo.AnimationOptions.DEFAULT_ANIMATION_RESOURCES_ID,
TransitionInfo.AnimationOptions.DEFAULT_ANIMATION_RESOURCES_ID,
Color.GREEN, false /* overrideTaskTransition */);
- mTransition.setOverrideAnimation(options, r, null /* startCallback */,
+ mTransition.setOverrideAnimation(options, null /* startCallback */,
null /* finishCallback */);
final TransitionInfo.Change displayChange = mInfo.getChanges().get(0);
@@ -2181,13 +2181,13 @@
@EnableFlags(Flags.FLAG_MOVE_ANIMATION_OPTIONS_TO_CHANGE)
@Test
public void testOverrideAnimationOptionsToInfoIfNecessary_customAnimOptionsWithTaskOverride() {
- ActivityRecord r = initializeOverrideAnimationOptionsTest();
+ initializeOverrideAnimationOptionsTest();
TransitionInfo.AnimationOptions options = TransitionInfo.AnimationOptions
.makeCustomAnimOptions("testPackage", Resources.ID_NULL,
TransitionInfo.AnimationOptions.DEFAULT_ANIMATION_RESOURCES_ID,
TransitionInfo.AnimationOptions.DEFAULT_ANIMATION_RESOURCES_ID,
Color.GREEN, true /* overrideTaskTransition */);
- mTransition.setOverrideAnimation(options, r, null /* startCallback */,
+ mTransition.setOverrideAnimation(options, null /* startCallback */,
null /* finishCallback */);
mTransition.overrideAnimationOptionsToInfoIfNecessary(mInfo);
@@ -2213,7 +2213,7 @@
options.getBackgroundColor(), activityChange.getBackgroundColor());
}
- private ActivityRecord initializeOverrideAnimationOptionsTest() {
+ private void initializeOverrideAnimationOptionsTest() {
mTransition = createTestTransition(TRANSIT_OPEN);
// Test set AnimationOptions for Activity and Task.
@@ -2241,7 +2241,6 @@
embeddedTf.getAnimationLeash()));
mInfo.addChange(new TransitionInfo.Change(null /* container */,
nonEmbeddedActivity.getAnimationLeash()));
- return nonEmbeddedActivity;
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index 39640fb..916c237 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -1189,7 +1189,7 @@
final int displayId = mDisplayContent.mDisplayId;
// Use real surface, so ViewportWindow's BlastBufferQueue can be created.
final ArrayList<SurfaceControl> surfaceControls = new ArrayList<>();
- mWm.mSurfaceControlFactory = s -> new SurfaceControl.Builder() {
+ mWm.mSurfaceControlFactory = () -> new SurfaceControl.Builder() {
@Override
public SurfaceControl build() {
final SurfaceControl sc = super.build();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index 88ce3a6..4f60106 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -51,7 +51,6 @@
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
import android.window.ScreenCapture;
import androidx.test.filters.SmallTest;
@@ -63,7 +62,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
-import java.util.function.Function;
+import java.util.function.Supplier;
/**
* Tests for the {@link DisplayContent#assignChildLayers(SurfaceControl.Transaction)} method.
@@ -126,8 +125,7 @@
private LayerRecordingTransaction mTransaction;
private SurfaceControl mPendingParent;
- HierarchyRecorder(SurfaceSession s, LayerRecordingTransaction transaction) {
- super(s);
+ HierarchyRecorder(LayerRecordingTransaction transaction) {
mTransaction = transaction;
}
@@ -146,8 +144,8 @@
}
}
- private static class HierarchyRecordingBuilderFactory implements Function<SurfaceSession,
- SurfaceControl.Builder> {
+ private static class HierarchyRecordingBuilderFactory
+ implements Supplier<SurfaceControl.Builder> {
private LayerRecordingTransaction mTransaction;
HierarchyRecordingBuilderFactory(LayerRecordingTransaction transaction) {
@@ -155,9 +153,8 @@
}
@Override
- public SurfaceControl.Builder apply(SurfaceSession s) {
- final LayerRecordingTransaction transaction = mTransaction;
- return new HierarchyRecorder(s, transaction);
+ public SurfaceControl.Builder get() {
+ return new HierarchyRecorder(mTransaction);
}
}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index ff4be55..d89c9c1 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -2339,6 +2339,7 @@
* @return True if the digits were processed as an MMI code, false otherwise.
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public boolean handleMmi(String dialString) {
ITelecomService service = getTelecomService();
if (service != null) {
@@ -2364,6 +2365,7 @@
* @return True if the digits were processed as an MMI code, false otherwise.
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
public boolean handleMmi(String dialString, PhoneAccountHandle accountHandle) {
ITelecomService service = getTelecomService();
if (service != null) {
diff --git a/telephony/common/android/telephony/LocationAccessPolicy.java b/telephony/common/android/telephony/LocationAccessPolicy.java
index feea55b..a678147 100644
--- a/telephony/common/android/telephony/LocationAccessPolicy.java
+++ b/telephony/common/android/telephony/LocationAccessPolicy.java
@@ -33,7 +33,6 @@
import android.widget.Toast;
import com.android.internal.telephony.TelephonyPermissions;
-import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.util.TelephonyUtils;
/**
@@ -312,18 +311,10 @@
// This avoid breaking legacy code that rely on public-facing APIs to access cell location,
// and it doesn't create an info leak risk because the cell location is stored in the phone
// process anyway, and the system server already has location access.
- if (Flags.supportPhoneUidCheckForMultiuser()) {
- if (TelephonyPermissions.isSystemOrPhone(query.callingUid)
- || UserHandle.isSameApp(query.callingUid, Process.NETWORK_STACK_UID)
- || UserHandle.isSameApp(query.callingUid, Process.ROOT_UID)) {
- return LocationPermissionResult.ALLOWED;
- }
- } else {
- if (query.callingUid == Process.PHONE_UID || query.callingUid == Process.SYSTEM_UID
- || query.callingUid == Process.NETWORK_STACK_UID
- || query.callingUid == Process.ROOT_UID) {
- return LocationPermissionResult.ALLOWED;
- }
+ if (TelephonyPermissions.isSystemOrPhone(query.callingUid)
+ || UserHandle.isSameApp(query.callingUid, Process.NETWORK_STACK_UID)
+ || UserHandle.isSameApp(query.callingUid, Process.ROOT_UID)) {
+ return LocationPermissionResult.ALLOWED;
}
// Check the system-wide requirements. If the location main switch is off and the caller is
diff --git a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
index 6482432..ff9cba2 100644
--- a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
@@ -33,7 +33,6 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.util.TelephonyUtils;
import java.util.ArrayList;
@@ -253,21 +252,17 @@
// 3. It has not been installed as an update from its system built-in version
// 4. It is in default state (not explicitly DISABLED/DISABLED_BY_USER/ENABLED)
// 5. It is currently installed for the calling user
- // TODO(b/329739019):
- // 1. Merge the nested if conditions below during flag cleaning up phase
- // 2. Support user case that NEW carrier app is added during OTA, when emerge.
- if (!Flags.hidePreinstalledCarrierAppAtMostOnce() || !hasRunEver) {
- if (!isUpdatedSystemApp(ai) && enabledSetting
- == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
- && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0) {
- Log.i(TAG, "Update state (" + packageName
- + "): DISABLED_UNTIL_USED for user " + userId);
- context.createContextAsUser(UserHandle.of(userId), 0)
- .getPackageManager()
- .setSystemAppState(
- packageName,
- PackageManager.SYSTEM_APP_STATE_UNINSTALLED);
- }
+ // TODO(b/329739019):Support user case that NEW carrier app is added during OTA
+ if (!hasRunEver && !isUpdatedSystemApp(ai) && enabledSetting
+ == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+ && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0) {
+ Log.i(TAG, "Update state (" + packageName
+ + "): DISABLED_UNTIL_USED for user " + userId);
+ context.createContextAsUser(UserHandle.of(userId), 0)
+ .getPackageManager()
+ .setSystemAppState(
+ packageName,
+ PackageManager.SYSTEM_APP_STATE_UNINSTALLED);
}
// Associated apps are more brittle, because we can't rely on the distinction
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 7ed26fb..b80610a 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -35,7 +35,6 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.flags.Flags;
import java.util.HashMap;
import java.util.HashSet;
@@ -934,12 +933,8 @@
* as system user or not.
*/
public static boolean isSystemOrPhone(int uid) {
- if (Flags.supportPhoneUidCheckForMultiuser()) {
- return UserHandle.isSameApp(uid, Process.SYSTEM_UID) || UserHandle.isSameApp(uid,
- Process.PHONE_UID);
- } else {
- return uid == Process.SYSTEM_UID || uid == Process.PHONE_UID;
- }
+ return UserHandle.isSameApp(uid, Process.SYSTEM_UID) || UserHandle.isSameApp(uid,
+ Process.PHONE_UID);
}
/**
@@ -947,11 +942,7 @@
* as system user or not.
*/
public static boolean isRootOrShell(int uid) {
- if (Flags.supportPhoneUidCheckForMultiuser()) {
- return UserHandle.isSameApp(uid, Process.ROOT_UID) || UserHandle.isSameApp(uid,
- Process.SHELL_UID);
- } else {
- return uid == Process.ROOT_UID || uid == Process.SHELL_UID;
- }
+ return UserHandle.isSameApp(uid, Process.ROOT_UID) || UserHandle.isSameApp(uid,
+ Process.SHELL_UID);
}
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 13bd5eb..aca0941 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -10098,8 +10098,8 @@
* The default value is 30 seconds.
*/
@FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
- public static final String KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT =
- "satellite_screen_off_inactivity_timeout_sec_int";
+ public static final String KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT =
+ "satellite_roaming_screen_off_inactivity_timeout_sec_int";
/**
* An integer key holds the timeout duration in seconds used to determine whether to exit P2P
@@ -10112,8 +10112,8 @@
* The default value is 180 seconds.
*/
@FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
- public static final String KEY_SATELLITE_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT =
- "satellite_p2p_sms_inactivity_timeout_sec_int";
+ public static final String KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT =
+ "satellite_roaming_p2p_sms_inactivity_timeout_sec_int";
/**
* An integer key holds the timeout duration in seconds used to determine whether to exit ESOS
@@ -10126,8 +10126,8 @@
* The default value is 600 seconds.
*/
@FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
- public static final String KEY_SATELLITE_ESOS_INACTIVITY_TIMEOUT_SEC_INT =
- "satellite_esos_inactivity_timeout_sec_int";
+ public static final String KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT =
+ "satellite_roaming_esos_inactivity_timeout_sec_int";
/**
* Indicating whether DUN APN should be disabled when the device is roaming. In that case,
@@ -11294,9 +11294,9 @@
sDefaults.putInt(KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT,
SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911);
sDefaults.putInt(KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT, 180);
- sDefaults.putInt(KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT, 30);
- sDefaults.putInt(KEY_SATELLITE_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT, 180);
- sDefaults.putInt(KEY_SATELLITE_ESOS_INACTIVITY_TIMEOUT_SEC_INT, 600);
+ sDefaults.putInt(KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT, 30);
+ sDefaults.putInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT, 180);
+ sDefaults.putInt(KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT, 600);
sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, "");
sDefaults.putBoolean(KEY_SUPPORTS_CALL_COMPOSER_BOOL, false);
sDefaults.putBoolean(KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL, false);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index f0850af..51e0c33 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1456,21 +1456,21 @@
public static final int SERVICE_CAPABILITY_MAX = SERVICE_CAPABILITY_DATA;
/**
- * Bitmask for {@code SERVICE_CAPABILITY_VOICE}.
+ * Bitmask for {@link #SERVICE_CAPABILITY_VOICE}.
* @hide
*/
public static final int SERVICE_CAPABILITY_VOICE_BITMASK =
serviceCapabilityToBitmask(SERVICE_CAPABILITY_VOICE);
/**
- * Bitmask for {@code SERVICE_CAPABILITY_SMS}.
+ * Bitmask for {@link #SERVICE_CAPABILITY_SMS}.
* @hide
*/
public static final int SERVICE_CAPABILITY_SMS_BITMASK =
serviceCapabilityToBitmask(SERVICE_CAPABILITY_SMS);
/**
- * Bitmask for {@code SERVICE_CAPABILITY_DATA}.
+ * Bitmask for {@link #SERVICE_CAPABILITY_DATA}.
* @hide
*/
public static final int SERVICE_CAPABILITY_DATA_BITMASK =
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index bc709ab..3e226cc 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -23,6 +23,7 @@
import static com.android.internal.util.Preconditions.checkNotNull;
import android.Manifest;
+import android.annotation.BoolRes;
import android.annotation.BytesLong;
import android.annotation.CallbackExecutor;
import android.annotation.CurrentTimeMillisLong;
@@ -6886,7 +6887,26 @@
}
}
- // TODO(b/316183370): replace all @code with @link in javadoc after feature is released
+ // Suppressing AndroidFrameworkCompatChange because we're querying vendor
+ // partition SDK level, not application's target SDK version.
+ @SuppressWarnings("AndroidFrameworkCompatChange")
+ private boolean hasCapability(@NonNull String feature, @BoolRes int legacySetting) {
+ if (mContext == null) return true;
+
+ if (mContext.getPackageManager().hasSystemFeature(feature)) return true;
+
+ // Check SDK version of the vendor partition.
+ final int vendorApiLevel = SystemProperties.getInt(
+ "ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT);
+ // Devices shipped with 2024Q2 or later are required to declare FEATURE_TELEPHONY_*
+ // for individual sub-features (calling, messaging, data), so there's no need to check
+ // the legacy setting.
+ if (vendorApiLevel < Build.VENDOR_API_2024_Q2) {
+ return mContext.getResources().getBoolean(legacySetting);
+ }
+ return false;
+ }
+
/**
* @return true if the current device is "voice capable".
* <p>
@@ -6900,16 +6920,14 @@
* PackageManager.FEATURE_TELEPHONY system feature, which is available
* on any device with a telephony radio, even if the device is
* data-only.
- * @deprecated Replaced by {@code #isDeviceVoiceCapable()}. Starting from Android 15, voice
+ * @deprecated Replaced by {@link #isDeviceVoiceCapable()}. Starting from Android 15, voice
* capability may also be overridden by carriers for a given subscription. For voice capable
- * device (when {@code #isDeviceVoiceCapable} return {@code true}), caller should check for
- * subscription-level voice capability as well. See {@code #isDeviceVoiceCapable} for details.
+ * device (when {@link #isDeviceVoiceCapable} return {@code true}), caller should check for
+ * subscription-level voice capability as well. See {@link #isDeviceVoiceCapable} for details.
*/
- @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
@Deprecated
public boolean isVoiceCapable() {
- if (mContext == null) return true;
- return mContext.getResources().getBoolean(
+ return hasCapability(PackageManager.FEATURE_TELEPHONY_CALLING,
com.android.internal.R.bool.config_voice_capable);
}
@@ -6927,12 +6945,11 @@
* <p>
* Starting from Android 15, voice capability may also be overridden by carrier for a given
* subscription on a voice capable device. To check if a subscription is "voice capable",
- * call method {@code SubscriptionInfo#getServiceCapabilities()} and check if
- * {@code SubscriptionManager#SERVICE_CAPABILITY_VOICE} is included.
+ * call method {@link SubscriptionInfo#getServiceCapabilities()} and check if
+ * {@link SubscriptionManager#SERVICE_CAPABILITY_VOICE} is included.
*
* @see SubscriptionInfo#getServiceCapabilities()
*/
- @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
@FlaggedApi(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE)
public boolean isDeviceVoiceCapable() {
return isVoiceCapable();
@@ -6946,15 +6963,14 @@
* <p>
* Note: Voicemail waiting sms, cell broadcasting sms, and MMS are
* disabled when device doesn't support sms.
- * @deprecated Replaced by {@code #isDeviceSmsCapable()}. Starting from Android 15, SMS
+ * @deprecated Replaced by {@link #isDeviceSmsCapable()}. Starting from Android 15, SMS
* capability may also be overridden by carriers for a given subscription. For SMS capable
- * device (when {@code #isDeviceSmsCapable} return {@code true}), caller should check for
- * subscription-level SMS capability as well. See {@code #isDeviceSmsCapable} for details.
+ * device (when {@link #isDeviceSmsCapable} return {@code true}), caller should check for
+ * subscription-level SMS capability as well. See {@link #isDeviceSmsCapable} for details.
*/
- @RequiresFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)
+ @Deprecated
public boolean isSmsCapable() {
- if (mContext == null) return true;
- return mContext.getResources().getBoolean(
+ return hasCapability(PackageManager.FEATURE_TELEPHONY_MESSAGING,
com.android.internal.R.bool.config_sms_capable);
}
@@ -6969,12 +6985,11 @@
* <p>
* Starting from Android 15, SMS capability may also be overridden by carriers for a given
* subscription on an SMS capable device. To check if a subscription is "SMS capable",
- * call method {@code SubscriptionInfo#getServiceCapabilities()} and check if
- * {@code SubscriptionManager#SERVICE_CAPABILITY_SMS} is included.
+ * call method {@link SubscriptionInfo#getServiceCapabilities()} and check if
+ * {@link SubscriptionManager#SERVICE_CAPABILITY_SMS} is included.
*
* @see SubscriptionInfo#getServiceCapabilities()
*/
- @RequiresFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)
@FlaggedApi(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE)
public boolean isDeviceSmsCapable() {
return isSmsCapable();
@@ -14542,10 +14557,8 @@
* data connections over the telephony network.
* <p>
*/
- @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean isDataCapable() {
- if (mContext == null) return true;
- return mContext.getResources().getBoolean(
+ return hasCapability(PackageManager.FEATURE_TELEPHONY_DATA,
com.android.internal.R.bool.config_mobile_data_capable);
}
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 83fc0dc..284e2bd 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -412,6 +412,22 @@
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_EMERGENCY_CALL_IN_PROGRESS = 27;
+ /**
+ * Disabling satellite is in progress.
+ *
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+ public static final int SATELLITE_RESULT_DISABLE_IN_PROGRESS = 28;
+
+ /**
+ * Enabling satellite is in progress.
+ *
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+ public static final int SATELLITE_RESULT_ENABLE_IN_PROGRESS = 29;
+
/** @hide */
@IntDef(prefix = {"SATELLITE_RESULT_"}, value = {
SATELLITE_RESULT_SUCCESS,
@@ -441,7 +457,9 @@
SATELLITE_RESULT_MODEM_TIMEOUT,
SATELLITE_RESULT_LOCATION_DISABLED,
SATELLITE_RESULT_LOCATION_NOT_AVAILABLE,
- SATELLITE_RESULT_EMERGENCY_CALL_IN_PROGRESS
+ SATELLITE_RESULT_EMERGENCY_CALL_IN_PROGRESS,
+ SATELLITE_RESULT_DISABLE_IN_PROGRESS,
+ SATELLITE_RESULT_ENABLE_IN_PROGRESS
})
@Retention(RetentionPolicy.SOURCE)
public @interface SatelliteResult {}
diff --git a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
index 51154e5..8b51321 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
+++ b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
@@ -83,7 +83,16 @@
* is enabled, this may also disable the cellular modem, and if the satellite modem is disabled,
* this may also re-enable the cellular modem.
*
+ * Framework might send an enable request to update the enable attributes of an already-started
+ * satellite session. In such cases, modem needs to apply the new enable attrbitues to the
+ * satellite session. Moreover, modem needs to report its current state and signal strength
+ * level to framework right after receiving this request from framework.
+ *
+ * Framework might send a disable request when an enable request is being processed. In such
+ * cases, modem needs to abort the enable request and process the disable request.
+ *
* @param enableAttributes The enable parameters that will be applied to the satellite session
+ * @param resultCallback The callback to receive the error code result of the operation.
*
* Valid result codes returned:
* SatelliteResult:SATELLITE_RESULT_SUCCESS
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl b/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl
index 162fe2b..24377c7 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl
@@ -22,7 +22,7 @@
@Backing(type="int")
enum SatelliteModemState {
/**
- * Satellite modem is in idle state.
+ * Satellite Idle state during which modem will scan for TN networks.
*/
SATELLITE_MODEM_STATE_IDLE = 0,
/**
@@ -46,13 +46,13 @@
*/
SATELLITE_MODEM_STATE_UNAVAILABLE = 5,
/**
- * The satellite modem is powered on but the device is not registered to a satellite cell.
+ * The satellite modem is powered on but the device is out of service.
*/
- SATELLITE_MODEM_STATE_NOT_CONNECTED = 6,
+ SATELLITE_MODEM_STATE_OUT_OF_SERVICE = 6,
/**
- * The satellite modem is powered on and the device is registered to a satellite cell.
+ * The satellite modem is powered on and the device is registered and in service.
*/
- SATELLITE_MODEM_STATE_CONNECTED = 7,
+ SATELLITE_MODEM_STATE_IN_SERVICE = 7,
/**
* 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.
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index e852e6b..e57c207 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -3394,4 +3394,19 @@
@JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ "android.Manifest.permission.SATELLITE_COMMUNICATION)")
void provisionSatellite(in List<SatelliteSubscriberInfo> list, in ResultReceiver result);
+
+ /**
+ * This API can be used by only CTS to override the cached value for the device overlay config
+ * value :
+ * config_satellite_gateway_service_package and
+ * config_satellite_carrier_roaming_esos_provisioned_class.
+ * These values are set before sending an intent to broadcast there are any change to list of
+ * subscriber informations.
+ *
+ * @param name the name is one of the following that constitute an intent.
+ * Component package name, or component class name.
+ * @return {@code true} if the setting is successful, {@code false} otherwise.
+ * @hide
+ */
+ boolean setSatelliteSubscriberIdListChangedIntentComponent(in String name);
}
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 29286e8..b92ba66 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -169,13 +169,13 @@
/**
* Set to false to disable SMS receiving, default is
- * the value of config_sms_capable
+ * the value of TelephonyManager.isDeviceSmsCapable
*/
static final String PROPERTY_SMS_RECEIVE = "telephony.sms.receive";
/**
* Set to false to disable SMS sending, default is
- * the value of config_sms_capable
+ * the value of TelephonyManager.isDeviceSmsCapable
*/
static final String PROPERTY_SMS_SEND = "telephony.sms.send";
diff --git a/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewControllerTests.java b/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewControllerTests.java
new file mode 100644
index 0000000..c7ebd3a
--- /dev/null
+++ b/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewControllerTests.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright 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.input.debug;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+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.content.Context;
+import android.graphics.Rect;
+import android.hardware.input.InputManager;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableContext;
+import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.InputDevice;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.server.input.InputManagerService;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+/**
+ * Build/Install/Run:
+ * atest TouchpadDebugViewControllerTests
+ */
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+public class TouchpadDebugViewControllerTests {
+ private static final int DEVICE_ID = 1000;
+ private static final String TAG = "TouchpadDebugViewController";
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ private Context mContext;
+ private TouchpadDebugViewController mTouchpadDebugViewController;
+ @Mock
+ private InputManager mInputManagerMock;
+ @Mock
+ private InputManagerService mInputManagerServiceMock;
+ @Mock
+ private WindowManager mWindowManagerMock;
+ private TestableLooper mTestableLooper;
+
+ @Before
+ public void setup() throws Exception {
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ TestableContext mTestableContext = new TestableContext(mContext);
+ mTestableContext.addMockSystemService(WindowManager.class, mWindowManagerMock);
+
+ Rect bounds = new Rect(0, 0, 2560, 1600);
+ WindowMetrics metrics = new WindowMetrics(bounds, new WindowInsets(bounds), 1.0f);
+
+ when(mWindowManagerMock.getCurrentWindowMetrics()).thenReturn(metrics);
+
+ unMockTouchpad();
+
+ mTestableLooper = TestableLooper.get(this);
+
+ mTestableContext.addMockSystemService(InputManager.class, mInputManagerMock);
+
+ mTouchpadDebugViewController = new TouchpadDebugViewController(mTestableContext,
+ mTestableLooper.getLooper(), mInputManagerServiceMock);
+ }
+
+ private InputDevice createTouchpadInputDevice(int id) {
+ return new InputDevice.Builder()
+ .setId(id)
+ .setSources(InputDevice.SOURCE_TOUCHPAD | InputDevice.SOURCE_MOUSE)
+ .setName("Test Device " + id)
+ .build();
+ }
+
+ private void mockTouchpad() {
+ when(mInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{DEVICE_ID});
+ when(mInputManagerMock.getInputDevice(eq(DEVICE_ID))).thenReturn(
+ createTouchpadInputDevice(DEVICE_ID));
+ }
+
+ private void unMockTouchpad() {
+ when(mInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{});
+ when(mInputManagerMock.getInputDevice(eq(DEVICE_ID))).thenReturn(null);
+ }
+
+ @Test
+ public void touchpadConnectedWhileSettingDisabled() throws Exception {
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false);
+
+ mockTouchpad();
+ mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID);
+
+ verify(mWindowManagerMock, never()).addView(any(), any());
+ verify(mWindowManagerMock, never()).removeView(any());
+ }
+
+ @Test
+ public void settingEnabledWhileNoTouchpadConnected() throws Exception {
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true);
+
+ verify(mWindowManagerMock, never()).addView(any(), any());
+ verify(mWindowManagerMock, never()).removeView(any());
+ }
+
+ @Test
+ public void touchpadConnectedWhileSettingEnabled() throws Exception {
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true);
+
+ mockTouchpad();
+ mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID);
+
+ verify(mWindowManagerMock, times(1)).addView(any(), any());
+ verify(mWindowManagerMock, never()).removeView(any());
+ }
+
+ @Test
+ public void touchpadConnectedWhileSettingEnabledThenDisabled() throws Exception {
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true);
+
+ mockTouchpad();
+ mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID);
+
+ verify(mWindowManagerMock, times(1)).addView(any(), any());
+ verify(mWindowManagerMock, never()).removeView(any());
+
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false);
+
+ verify(mWindowManagerMock, times(1)).addView(any(), any());
+ verify(mWindowManagerMock, times(1)).removeView(any());
+ }
+
+ @Test
+ public void touchpadConnectedWhileSettingDisabledThenEnabled() throws Exception {
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false);
+
+ mockTouchpad();
+ mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID);
+
+ verify(mWindowManagerMock, never()).addView(any(), any());
+ verify(mWindowManagerMock, never()).removeView(any());
+
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true);
+
+ verify(mWindowManagerMock, times(1)).addView(any(), any());
+ verify(mWindowManagerMock, never()).removeView(any());
+ }
+
+ @Test
+ public void touchpadConnectedWhileSettingDisabledThenTouchpadDisconnected() throws Exception {
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false);
+
+ mockTouchpad();
+ mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID);
+
+ verify(mWindowManagerMock, never()).addView(any(), any());
+ verify(mWindowManagerMock, never()).removeView(any());
+
+ unMockTouchpad();
+ mTouchpadDebugViewController.onInputDeviceRemoved(DEVICE_ID);
+
+ verify(mWindowManagerMock, never()).addView(any(), any());
+ verify(mWindowManagerMock, never()).removeView(any());
+ }
+
+ @Test
+ public void touchpadConnectedWhileSettingEnabledThenTouchpadDisconnectedThenSettingDisabled()
+ throws Exception {
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true);
+
+ mockTouchpad();
+ mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID);
+
+ verify(mWindowManagerMock, times(1)).addView(any(), any());
+ verify(mWindowManagerMock, never()).removeView(any());
+
+ unMockTouchpad();
+ mTouchpadDebugViewController.onInputDeviceRemoved(DEVICE_ID);
+
+ verify(mWindowManagerMock, times(1)).addView(any(), any());
+ verify(mWindowManagerMock, times(1)).removeView(any());
+
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false);
+
+ verify(mWindowManagerMock, times(1)).addView(any(), any());
+ verify(mWindowManagerMock, times(1)).removeView(any());
+ }
+}
diff --git a/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewTest.java b/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewTest.java
new file mode 100644
index 0000000..0f08be2
--- /dev/null
+++ b/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewTest.java
@@ -0,0 +1,328 @@
+/*
+ * Copyright 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.input.debug;
+
+import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.testing.TestableContext;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.cts.input.MotionEventBuilder;
+import com.android.cts.input.PointerBuilder;
+import com.android.server.input.TouchpadFingerState;
+import com.android.server.input.TouchpadHardwareState;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Build/Install/Run:
+ * atest TouchpadDebugViewTest
+ */
+@RunWith(AndroidJUnit4.class)
+public class TouchpadDebugViewTest {
+ private static final int TOUCHPAD_DEVICE_ID = 6;
+
+ private TouchpadDebugView mTouchpadDebugView;
+ private WindowManager.LayoutParams mWindowLayoutParams;
+
+ @Mock
+ WindowManager mWindowManager;
+
+ Rect mWindowBounds;
+ WindowMetrics mWindowMetrics;
+ TestableContext mTestableContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ mTestableContext = new TestableContext(context);
+
+ mTestableContext.addMockSystemService(WindowManager.class, mWindowManager);
+
+ mWindowBounds = new Rect(0, 0, 2560, 1600);
+ mWindowMetrics = new WindowMetrics(mWindowBounds, new WindowInsets(mWindowBounds), 1.0f);
+
+ when(mWindowManager.getCurrentWindowMetrics()).thenReturn(mWindowMetrics);
+
+ mTouchpadDebugView = new TouchpadDebugView(mTestableContext, TOUCHPAD_DEVICE_ID);
+
+ mTouchpadDebugView.measure(
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
+ );
+
+ doAnswer(invocation -> {
+ mTouchpadDebugView.layout(0, 0, mTouchpadDebugView.getMeasuredWidth(),
+ mTouchpadDebugView.getMeasuredHeight());
+ return null;
+ }).when(mWindowManager).addView(any(), any());
+
+ doAnswer(invocation -> {
+ mTouchpadDebugView.layout(0, 0, mTouchpadDebugView.getMeasuredWidth(),
+ mTouchpadDebugView.getMeasuredHeight());
+ return null;
+ }).when(mWindowManager).updateViewLayout(any(), any());
+
+ mWindowLayoutParams = mTouchpadDebugView.getWindowLayoutParams();
+ mWindowLayoutParams.x = 20;
+ mWindowLayoutParams.y = 20;
+
+ mTouchpadDebugView.layout(0, 0, mTouchpadDebugView.getMeasuredWidth(),
+ mTouchpadDebugView.getMeasuredHeight());
+ }
+
+ @Test
+ public void testDragView() {
+ // Initial view position relative to screen.
+ int initialX = mWindowLayoutParams.x;
+ int initialY = mWindowLayoutParams.y;
+
+ float offsetX = ViewConfiguration.get(mTestableContext).getScaledTouchSlop() + 10;
+ float offsetY = ViewConfiguration.get(mTestableContext).getScaledTouchSlop() + 10;
+
+ // Simulate ACTION_DOWN event (initial touch).
+ MotionEvent actionDown = new MotionEventBuilder(MotionEvent.ACTION_DOWN, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(40f)
+ .y(40f)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionDown);
+
+ verify(mWindowManager, times(0)).updateViewLayout(any(), any());
+
+ // Simulate ACTION_MOVE event (dragging to the right).
+ MotionEvent actionMove = new MotionEventBuilder(MotionEvent.ACTION_MOVE, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(40f + offsetX)
+ .y(40f + offsetY)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionMove);
+
+ ArgumentCaptor<WindowManager.LayoutParams> mWindowLayoutParamsCaptor =
+ ArgumentCaptor.forClass(WindowManager.LayoutParams.class);
+ verify(mWindowManager).updateViewLayout(any(), mWindowLayoutParamsCaptor.capture());
+
+ // Verify position after ACTION_MOVE
+ assertEquals(initialX + (long) offsetX, mWindowLayoutParamsCaptor.getValue().x);
+ assertEquals(initialY + (long) offsetY, mWindowLayoutParamsCaptor.getValue().y);
+
+ // Simulate ACTION_UP event (release touch).
+ MotionEvent actionUp = new MotionEventBuilder(MotionEvent.ACTION_UP, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(40f + offsetX)
+ .y(40f + offsetY)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionUp);
+
+ assertEquals(initialX + (long) offsetX, mWindowLayoutParamsCaptor.getValue().x);
+ assertEquals(initialY + (long) offsetY, mWindowLayoutParamsCaptor.getValue().y);
+ }
+
+ @Test
+ public void testDragViewOutOfBounds() {
+ int initialX = mWindowLayoutParams.x;
+ int initialY = mWindowLayoutParams.y;
+
+ MotionEvent actionDown = new MotionEventBuilder(MotionEvent.ACTION_DOWN, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(initialX + 10f)
+ .y(initialY + 10f)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionDown);
+
+ verify(mWindowManager, times(0)).updateViewLayout(any(), any());
+
+ // Simulate ACTION_MOVE event (dragging far to the right and bottom, beyond screen bounds)
+ MotionEvent actionMove = new MotionEventBuilder(MotionEvent.ACTION_MOVE, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(mWindowBounds.width() + mTouchpadDebugView.getWidth())
+ .y(mWindowBounds.height() + mTouchpadDebugView.getHeight())
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionMove);
+
+ ArgumentCaptor<WindowManager.LayoutParams> mWindowLayoutParamsCaptor =
+ ArgumentCaptor.forClass(WindowManager.LayoutParams.class);
+ verify(mWindowManager).updateViewLayout(any(), mWindowLayoutParamsCaptor.capture());
+
+ // Verify the view has been clamped to the right and bottom edges of the screen
+ assertEquals(mWindowBounds.width() - mTouchpadDebugView.getWidth(),
+ mWindowLayoutParamsCaptor.getValue().x);
+ assertEquals(mWindowBounds.height() - mTouchpadDebugView.getHeight(),
+ mWindowLayoutParamsCaptor.getValue().y);
+
+ MotionEvent actionUp = new MotionEventBuilder(MotionEvent.ACTION_UP, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(mWindowBounds.width() + mTouchpadDebugView.getWidth())
+ .y(mWindowBounds.height() + mTouchpadDebugView.getHeight())
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionUp);
+
+ // Verify the view has been clamped to the right and bottom edges of the screen
+ assertEquals(mWindowBounds.width() - mTouchpadDebugView.getWidth(),
+ mWindowLayoutParamsCaptor.getValue().x);
+ assertEquals(mWindowBounds.height() - mTouchpadDebugView.getHeight(),
+ mWindowLayoutParamsCaptor.getValue().y);
+ }
+
+ @Test
+ public void testSlopOffset() {
+ int initialX = mWindowLayoutParams.x;
+ int initialY = mWindowLayoutParams.y;
+
+ float offsetX = ViewConfiguration.get(mTestableContext).getScaledTouchSlop() / 2.0f;
+ float offsetY = -(ViewConfiguration.get(mTestableContext).getScaledTouchSlop() / 2.0f);
+
+ MotionEvent actionDown = new MotionEventBuilder(MotionEvent.ACTION_DOWN, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(initialX)
+ .y(initialY)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionDown);
+
+ MotionEvent actionMove = new MotionEventBuilder(MotionEvent.ACTION_MOVE, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(initialX + offsetX)
+ .y(initialY + offsetY)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionMove);
+
+ MotionEvent actionUp = new MotionEventBuilder(MotionEvent.ACTION_UP, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(initialX)
+ .y(initialY)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionUp);
+
+ // In this case the updateViewLayout() method wouldn't be called because the drag
+ // distance hasn't exceeded the slop
+ verify(mWindowManager, times(0)).updateViewLayout(any(), any());
+ }
+
+ @Test
+ public void testViewReturnsToInitialPositionOnCancel() {
+ int initialX = mWindowLayoutParams.x;
+ int initialY = mWindowLayoutParams.y;
+
+ float offsetX = 50;
+ float offsetY = 50;
+
+ MotionEvent actionDown = new MotionEventBuilder(MotionEvent.ACTION_DOWN, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(initialX)
+ .y(initialY)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionDown);
+
+ MotionEvent actionMove = new MotionEventBuilder(MotionEvent.ACTION_MOVE, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(initialX + offsetX)
+ .y(initialY + offsetY)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionMove);
+
+ ArgumentCaptor<WindowManager.LayoutParams> mWindowLayoutParamsCaptor =
+ ArgumentCaptor.forClass(WindowManager.LayoutParams.class);
+ verify(mWindowManager).updateViewLayout(any(), mWindowLayoutParamsCaptor.capture());
+
+ assertEquals(initialX + (long) offsetX, mWindowLayoutParamsCaptor.getValue().x);
+ assertEquals(initialY + (long) offsetY, mWindowLayoutParamsCaptor.getValue().y);
+
+ // Simulate ACTION_CANCEL event (canceling the touch event stream)
+ MotionEvent actionCancel = new MotionEventBuilder(MotionEvent.ACTION_CANCEL,
+ SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(initialX + offsetX)
+ .y(initialY + offsetY)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionCancel);
+
+ // Verify the view returns to its initial position
+ verify(mWindowManager, times(2)).updateViewLayout(any(),
+ mWindowLayoutParamsCaptor.capture());
+ assertEquals(initialX, mWindowLayoutParamsCaptor.getValue().x);
+ assertEquals(initialY, mWindowLayoutParamsCaptor.getValue().y);
+ }
+
+ @Test
+ public void testTouchpadClick() {
+ View child;
+
+ mTouchpadDebugView.updateHardwareState(
+ new TouchpadHardwareState(0, 1 /* buttonsDown */, 0, 0,
+ new TouchpadFingerState[0]));
+
+ for (int i = 0; i < mTouchpadDebugView.getChildCount(); i++) {
+ child = mTouchpadDebugView.getChildAt(i);
+ assertEquals(((ColorDrawable) child.getBackground()).getColor(), Color.BLUE);
+ }
+
+ mTouchpadDebugView.updateHardwareState(
+ new TouchpadHardwareState(0, 0 /* buttonsDown */, 0, 0,
+ new TouchpadFingerState[0]));
+
+ for (int i = 0; i < mTouchpadDebugView.getChildCount(); i++) {
+ child = mTouchpadDebugView.getChildAt(i);
+ assertEquals(((ColorDrawable) child.getBackground()).getColor(), Color.RED);
+ }
+
+ mTouchpadDebugView.updateHardwareState(
+ new TouchpadHardwareState(0, 1 /* buttonsDown */, 0, 0,
+ new TouchpadFingerState[0]));
+
+ for (int i = 0; i < mTouchpadDebugView.getChildCount(); i++) {
+ child = mTouchpadDebugView.getChildAt(i);
+ assertEquals(((ColorDrawable) child.getBackground()).getColor(), Color.BLUE);
+ }
+ }
+}
diff --git a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
index 6db5f82..189de6b 100644
--- a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
@@ -16,8 +16,6 @@
package com.android.internal.protolog;
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
@@ -30,7 +28,6 @@
import static java.io.File.createTempFile;
-import android.content.Context;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.tools.ScenarioBuilder;
@@ -45,6 +42,7 @@
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.internal.protolog.ProtoLogConfigurationService.ViewerConfigFileTracer;
import com.android.internal.protolog.common.IProtoLogGroup;
import com.android.internal.protolog.common.LogDataType;
import com.android.internal.protolog.common.LogLevel;
@@ -53,11 +51,11 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
import perfetto.protos.Protolog;
import perfetto.protos.ProtologCommon;
@@ -75,6 +73,8 @@
@Presubmit
@RunWith(JUnit4.class)
public class PerfettoProtoLogImplTest {
+ private static final String TEST_PROTOLOG_DATASOURCE_NAME = "test.android.protolog";
+ private static final String MOCK_VIEWER_CONFIG_FILE = "my/mock/viewer/config/file.pb";
private final File mTracingDirectory = InstrumentationRegistry.getInstrumentation()
.getTargetContext().getFilesDir();
@@ -91,28 +91,19 @@
new TraceConfig(false, true, false)
);
- private PerfettoProtoLogImpl mProtoLog;
- private Protolog.ProtoLogViewerConfig.Builder mViewerConfigBuilder;
- private File mFile;
- private Runnable mCacheUpdater;
+ private static ProtoLogConfigurationService sProtoLogConfigurationService;
+ private static PerfettoProtoLogImpl sProtoLog;
+ private static Protolog.ProtoLogViewerConfig.Builder sViewerConfigBuilder;
+ private static Runnable sCacheUpdater;
- private ProtoLogViewerConfigReader mReader;
+ private static ProtoLogViewerConfigReader sReader;
public PerfettoProtoLogImplTest() throws IOException {
}
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- final Context testContext = getInstrumentation().getContext();
- mFile = testContext.getFileStreamPath("tracing_test.dat");
- //noinspection ResultOfMethodCallIgnored
- mFile.delete();
-
- TestProtoLogGroup.TEST_GROUP.setLogToLogcat(false);
- TestProtoLogGroup.TEST_GROUP.setLogToProto(false);
-
- mViewerConfigBuilder = Protolog.ProtoLogViewerConfig.newBuilder()
+ @BeforeClass
+ public static void setUp() throws Exception {
+ sViewerConfigBuilder = Protolog.ProtoLogViewerConfig.newBuilder()
.addGroups(
Protolog.ProtoLogViewerConfig.Group.newBuilder()
.setId(1)
@@ -158,36 +149,62 @@
ViewerConfigInputStreamProvider viewerConfigInputStreamProvider = Mockito.mock(
ViewerConfigInputStreamProvider.class);
Mockito.when(viewerConfigInputStreamProvider.getInputStream())
- .thenAnswer(it -> new ProtoInputStream(mViewerConfigBuilder.build().toByteArray()));
+ .thenAnswer(it -> new ProtoInputStream(sViewerConfigBuilder.build().toByteArray()));
- mCacheUpdater = () -> {};
- mReader = Mockito.spy(new ProtoLogViewerConfigReader(viewerConfigInputStreamProvider));
- mProtoLog = new PerfettoProtoLogImpl(
- viewerConfigInputStreamProvider, mReader,
- () -> mCacheUpdater.run(), TestProtoLogGroup.values());
+ sCacheUpdater = () -> {};
+ sReader = Mockito.spy(new ProtoLogViewerConfigReader(viewerConfigInputStreamProvider));
+
+ final ProtoLogDataSourceBuilder dataSourceBuilder =
+ (onStart, onFlush, onStop) -> new ProtoLogDataSource(
+ onStart, onFlush, onStop, TEST_PROTOLOG_DATASOURCE_NAME);
+ final ViewerConfigFileTracer tracer = (dataSource, viewerConfigFilePath) -> {
+ Utils.dumpViewerConfig(dataSource, () -> {
+ if (!viewerConfigFilePath.equals(MOCK_VIEWER_CONFIG_FILE)) {
+ throw new RuntimeException(
+ "Unexpected viewer config file path provided");
+ }
+ return new ProtoInputStream(sViewerConfigBuilder.build().toByteArray());
+ });
+ };
+ sProtoLogConfigurationService = new ProtoLogConfigurationService(dataSourceBuilder, tracer);
+
+ if (android.tracing.Flags.clientSideProtoLogging()) {
+ sProtoLog = new PerfettoProtoLogImpl(
+ MOCK_VIEWER_CONFIG_FILE, sReader, () -> sCacheUpdater.run(),
+ TestProtoLogGroup.values(), dataSourceBuilder, sProtoLogConfigurationService);
+ } else {
+ sProtoLog = new PerfettoProtoLogImpl(
+ viewerConfigInputStreamProvider, sReader, () -> sCacheUpdater.run(),
+ TestProtoLogGroup.values(), dataSourceBuilder, sProtoLogConfigurationService);
+ }
+ }
+
+ @Before
+ public void before() {
+ Mockito.reset(sReader);
+
+ TestProtoLogGroup.TEST_GROUP.setLogToLogcat(false);
+ TestProtoLogGroup.TEST_GROUP.setLogToProto(false);
}
@After
public void tearDown() {
- if (mFile != null) {
- //noinspection ResultOfMethodCallIgnored
- mFile.delete();
- }
ProtoLogImpl.setSingleInstance(null);
}
@Test
public void isEnabled_returnsFalseByDefault() {
- assertFalse(mProtoLog.isProtoEnabled());
+ assertFalse(sProtoLog.isProtoEnabled());
}
@Test
public void isEnabled_returnsTrueAfterStart() {
- PerfettoTraceMonitor traceMonitor =
- PerfettoTraceMonitor.newBuilder().enableProtoLog().build();
+ PerfettoTraceMonitor traceMonitor = PerfettoTraceMonitor.newBuilder()
+ .enableProtoLog(TEST_PROTOLOG_DATASOURCE_NAME)
+ .build();
try {
traceMonitor.start();
- assertTrue(mProtoLog.isProtoEnabled());
+ assertTrue(sProtoLog.isProtoEnabled());
} finally {
traceMonitor.stop(mWriter);
}
@@ -195,35 +212,37 @@
@Test
public void isEnabled_returnsFalseAfterStop() {
- PerfettoTraceMonitor traceMonitor =
- PerfettoTraceMonitor.newBuilder().enableProtoLog().build();
+ PerfettoTraceMonitor traceMonitor = PerfettoTraceMonitor.newBuilder()
+ .enableProtoLog(TEST_PROTOLOG_DATASOURCE_NAME)
+ .build();
try {
traceMonitor.start();
- assertTrue(mProtoLog.isProtoEnabled());
+ assertTrue(sProtoLog.isProtoEnabled());
} finally {
traceMonitor.stop(mWriter);
}
- assertFalse(mProtoLog.isProtoEnabled());
+ assertFalse(sProtoLog.isProtoEnabled());
}
@Test
public void defaultMode() throws IOException {
- PerfettoTraceMonitor traceMonitor =
- PerfettoTraceMonitor.newBuilder().enableProtoLog(false).build();
+ PerfettoTraceMonitor traceMonitor = PerfettoTraceMonitor.newBuilder()
+ .enableProtoLog(false, List.of(), TEST_PROTOLOG_DATASOURCE_NAME)
+ .build();
try {
traceMonitor.start();
// Shouldn't be logging anything except WTF unless explicitly requested in the group
// override.
- mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
+ sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
LogDataType.BOOLEAN, new Object[]{true});
- mProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2,
+ sProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2,
LogDataType.BOOLEAN, new Object[]{true});
- mProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3,
+ sProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3,
LogDataType.BOOLEAN, new Object[]{true});
- mProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4,
+ sProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4,
LogDataType.BOOLEAN, new Object[]{true});
- mProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5,
+ sProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5,
LogDataType.BOOLEAN, new Object[]{true});
} finally {
traceMonitor.stop(mWriter);
@@ -238,22 +257,24 @@
@Test
public void respectsOverrideConfigs_defaultMode() throws IOException {
- PerfettoTraceMonitor traceMonitor =
- PerfettoTraceMonitor.newBuilder().enableProtoLog(true,
+ PerfettoTraceMonitor traceMonitor = PerfettoTraceMonitor.newBuilder()
+ .enableProtoLog(
+ true,
List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride(
- TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.DEBUG, true)))
- .build();
+ TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.DEBUG, true)),
+ TEST_PROTOLOG_DATASOURCE_NAME
+ ).build();
try {
traceMonitor.start();
- mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
+ sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
LogDataType.BOOLEAN, new Object[]{true});
- mProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2,
+ sProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2,
LogDataType.BOOLEAN, new Object[]{true});
- mProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3,
+ sProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3,
LogDataType.BOOLEAN, new Object[]{true});
- mProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4,
+ sProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4,
LogDataType.BOOLEAN, new Object[]{true});
- mProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5,
+ sProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5,
LogDataType.BOOLEAN, new Object[]{true});
} finally {
traceMonitor.stop(mWriter);
@@ -273,21 +294,23 @@
@Test
public void respectsOverrideConfigs_allEnabledMode() throws IOException {
PerfettoTraceMonitor traceMonitor =
- PerfettoTraceMonitor.newBuilder().enableProtoLog(true,
+ PerfettoTraceMonitor.newBuilder().enableProtoLog(
+ true,
List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride(
- TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.WARN, false)))
- .build();
+ TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.WARN, false)),
+ TEST_PROTOLOG_DATASOURCE_NAME
+ ).build();
try {
traceMonitor.start();
- mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
+ sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
LogDataType.BOOLEAN, new Object[]{true});
- mProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2,
+ sProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2,
LogDataType.BOOLEAN, new Object[]{true});
- mProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3,
+ sProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3,
LogDataType.BOOLEAN, new Object[]{true});
- mProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4,
+ sProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4,
LogDataType.BOOLEAN, new Object[]{true});
- mProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5,
+ sProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5,
LogDataType.BOOLEAN, new Object[]{true});
} finally {
traceMonitor.stop(mWriter);
@@ -304,20 +327,20 @@
@Test
public void respectsAllEnabledMode() throws IOException {
- PerfettoTraceMonitor traceMonitor =
- PerfettoTraceMonitor.newBuilder().enableProtoLog(true, List.of())
- .build();
+ PerfettoTraceMonitor traceMonitor = PerfettoTraceMonitor.newBuilder()
+ .enableProtoLog(true, List.of(), TEST_PROTOLOG_DATASOURCE_NAME)
+ .build();
try {
traceMonitor.start();
- mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
+ sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
LogDataType.BOOLEAN, new Object[]{true});
- mProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2,
+ sProtoLog.log(LogLevel.VERBOSE, TestProtoLogGroup.TEST_GROUP, 2,
LogDataType.BOOLEAN, new Object[]{true});
- mProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3,
+ sProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP, 3,
LogDataType.BOOLEAN, new Object[]{true});
- mProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4,
+ sProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP, 4,
LogDataType.BOOLEAN, new Object[]{true});
- mProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5,
+ sProtoLog.log(LogLevel.WTF, TestProtoLogGroup.TEST_GROUP, 5,
LogDataType.BOOLEAN, new Object[]{true});
} finally {
traceMonitor.stop(mWriter);
@@ -336,8 +359,8 @@
@Test
public void log_logcatEnabled() {
- when(mReader.getViewerString(anyLong())).thenReturn("test %b %d %% 0x%x %s %f");
- PerfettoProtoLogImpl implSpy = Mockito.spy(mProtoLog);
+ when(sReader.getViewerString(anyLong())).thenReturn("test %b %d %% 0x%x %s %f");
+ PerfettoProtoLogImpl implSpy = Mockito.spy(sProtoLog);
TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true);
TestProtoLogGroup.TEST_GROUP.setLogToProto(false);
@@ -348,13 +371,13 @@
verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq(
LogLevel.INFO),
eq("test true 10000 % 0x7530 test 3.0E-6"));
- verify(mReader).getViewerString(eq(1234L));
+ verify(sReader).getViewerString(eq(1234L));
}
@Test
public void log_logcatEnabledInvalidMessage() {
- when(mReader.getViewerString(anyLong())).thenReturn("test %b %d %% %x %s %f");
- PerfettoProtoLogImpl implSpy = Mockito.spy(mProtoLog);
+ when(sReader.getViewerString(anyLong())).thenReturn("test %b %d %% %x %s %f");
+ PerfettoProtoLogImpl implSpy = Mockito.spy(sProtoLog);
TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true);
TestProtoLogGroup.TEST_GROUP.setLogToProto(false);
@@ -366,29 +389,32 @@
LogLevel.INFO),
eq("FORMAT_ERROR \"test %b %d %% %x %s %f\", "
+ "args=(true, 10000, 1.0E-4, 2.0E-5, test)"));
- verify(mReader).getViewerString(eq(1234L));
+ verify(sReader).getViewerString(eq(1234L));
}
@Test
public void log_logcatEnabledNoMessage() {
- when(mReader.getViewerString(anyLong())).thenReturn(null);
- PerfettoProtoLogImpl implSpy = Mockito.spy(mProtoLog);
+ when(sReader.getViewerString(anyLong())).thenReturn(null);
+ PerfettoProtoLogImpl implSpy = Mockito.spy(sProtoLog);
TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true);
TestProtoLogGroup.TEST_GROUP.setLogToProto(false);
- implSpy.log(
+ var assertion = assertThrows(RuntimeException.class, () -> implSpy.log(
LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321,
- new Object[]{5});
+ new Object[]{5}));
- verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq(
- LogLevel.INFO), eq("UNKNOWN MESSAGE args = (5)"));
- verify(mReader).getViewerString(eq(1234L));
+ verify(implSpy, never()).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq(
+ LogLevel.INFO), any());
+ verify(sReader).getViewerString(eq(1234L));
+
+ Truth.assertThat(assertion).hasMessageThat()
+ .contains("Failed to get log message with hash 1234 and args (5)");
}
@Test
public void log_logcatDisabled() {
- when(mReader.getViewerString(anyLong())).thenReturn("test %d");
- PerfettoProtoLogImpl implSpy = Mockito.spy(mProtoLog);
+ when(sReader.getViewerString(anyLong())).thenReturn("test %d");
+ PerfettoProtoLogImpl implSpy = Mockito.spy(sProtoLog);
TestProtoLogGroup.TEST_GROUP.setLogToLogcat(false);
implSpy.log(
@@ -396,7 +422,7 @@
new Object[]{5});
verify(implSpy, never()).passToLogcat(any(), any(), any());
- verify(mReader, never()).getViewerString(anyLong());
+ verify(sReader, never()).getViewerString(anyLong());
}
@Test
@@ -405,16 +431,18 @@
ProtologCommon.ProtoLogLevel.PROTOLOG_LEVEL_INFO,
"My test message :: %s, %d, %o, %x, %f, %e, %g, %b");
- PerfettoTraceMonitor traceMonitor =
- PerfettoTraceMonitor.newBuilder().enableProtoLog().build();
+ PerfettoTraceMonitor traceMonitor = PerfettoTraceMonitor.newBuilder()
+ .enableProtoLog(TEST_PROTOLOG_DATASOURCE_NAME)
+ .build();
long before;
long after;
try {
+ assertFalse(sProtoLog.isProtoEnabled());
traceMonitor.start();
- assertTrue(mProtoLog.isProtoEnabled());
+ assertTrue(sProtoLog.isProtoEnabled());
before = SystemClock.elapsedRealtimeNanos();
- mProtoLog.log(
+ sProtoLog.log(
LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, messageHash,
0b1110101001010100,
new Object[]{"test", 1, 2, 3, 0.4, 0.5, 0.6, true});
@@ -432,21 +460,23 @@
Truth.assertThat(protolog.messages.getFirst().getTimestamp().getElapsedNanos())
.isAtMost(after);
Truth.assertThat(protolog.messages.getFirst().getMessage())
- .isEqualTo("My test message :: test, 2, 4, 6, 0.400000, 5.000000e-01, 0.6, true");
+ .isEqualTo(
+ "My test message :: test, 1, 2, 3, 0.400000, 5.000000e-01, 0.6, true");
}
@Test
public void log_noProcessing() throws IOException {
- PerfettoTraceMonitor traceMonitor =
- PerfettoTraceMonitor.newBuilder().enableProtoLog().build();
+ PerfettoTraceMonitor traceMonitor = PerfettoTraceMonitor.newBuilder()
+ .enableProtoLog(TEST_PROTOLOG_DATASOURCE_NAME)
+ .build();
long before;
long after;
try {
traceMonitor.start();
- assertTrue(mProtoLog.isProtoEnabled());
+ assertTrue(sProtoLog.isProtoEnabled());
before = SystemClock.elapsedRealtimeNanos();
- mProtoLog.log(
+ sProtoLog.log(
LogLevel.INFO, TestProtoLogGroup.TEST_GROUP,
"My test message :: %s, %d, %x, %f, %b",
"test", 1, 3, 0.4, true);
@@ -464,16 +494,17 @@
Truth.assertThat(protolog.messages.getFirst().getTimestamp().getElapsedNanos())
.isAtMost(after);
Truth.assertThat(protolog.messages.getFirst().getMessage())
- .isEqualTo("My test message :: test, 2, 6, 0.400000, true");
+ .isEqualTo("My test message :: test, 1, 3, 0.400000, true");
}
@Test
public void supportsLocationInformation() throws IOException {
- PerfettoTraceMonitor traceMonitor =
- PerfettoTraceMonitor.newBuilder().enableProtoLog(true).build();
+ PerfettoTraceMonitor traceMonitor = PerfettoTraceMonitor.newBuilder()
+ .enableProtoLog(true, List.of(), TEST_PROTOLOG_DATASOURCE_NAME)
+ .build();
try {
traceMonitor.start();
- mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
+ sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
LogDataType.BOOLEAN, new Object[]{true});
} finally {
traceMonitor.stop(mWriter);
@@ -489,7 +520,7 @@
private long addMessageToConfig(ProtologCommon.ProtoLogLevel logLevel, String message) {
final long messageId = new Random().nextLong();
- mViewerConfigBuilder.addMessages(Protolog.ProtoLogViewerConfig.MessageData.newBuilder()
+ sViewerConfigBuilder.addMessages(Protolog.ProtoLogViewerConfig.MessageData.newBuilder()
.setMessageId(messageId)
.setMessage(message)
.setLevel(logLevel)
@@ -504,14 +535,15 @@
final long messageHash = addMessageToConfig(
ProtologCommon.ProtoLogLevel.PROTOLOG_LEVEL_INFO,
"My test message :: %s, %d, %f, %b");
- PerfettoTraceMonitor traceMonitor =
- PerfettoTraceMonitor.newBuilder().enableProtoLog().build();
+ PerfettoTraceMonitor traceMonitor = PerfettoTraceMonitor.newBuilder()
+ .enableProtoLog(TEST_PROTOLOG_DATASOURCE_NAME)
+ .build();
long before;
long after;
try {
traceMonitor.start();
before = SystemClock.elapsedRealtimeNanos();
- mProtoLog.log(
+ sProtoLog.log(
LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, messageHash,
0b01100100,
new Object[]{"test", 1, 0.1, true});
@@ -526,11 +558,12 @@
@Test
public void log_protoDisabled() throws Exception {
- PerfettoTraceMonitor traceMonitor =
- PerfettoTraceMonitor.newBuilder().enableProtoLog(false).build();
+ PerfettoTraceMonitor traceMonitor = PerfettoTraceMonitor.newBuilder()
+ .enableProtoLog(false, List.of(), TEST_PROTOLOG_DATASOURCE_NAME)
+ .build();
try {
traceMonitor.start();
- mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
+ sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
0b11, new Object[]{true});
} finally {
traceMonitor.stop(mWriter);
@@ -544,16 +577,18 @@
@Test
public void stackTraceTrimmed() throws IOException {
- PerfettoTraceMonitor traceMonitor =
- PerfettoTraceMonitor.newBuilder().enableProtoLog(true,
+ PerfettoTraceMonitor traceMonitor = PerfettoTraceMonitor.newBuilder()
+ .enableProtoLog(
+ true,
List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride(
TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.DEBUG,
- true)))
- .build();
+ true)),
+ TEST_PROTOLOG_DATASOURCE_NAME
+ ).build();
try {
traceMonitor.start();
- ProtoLogImpl.setSingleInstance(mProtoLog);
+ ProtoLogImpl.setSingleInstance(sProtoLog);
ProtoLogImpl.d(TestProtoLogGroup.TEST_GROUP, 1,
0b11, true);
} finally {
@@ -577,20 +612,20 @@
@Test
public void cacheIsUpdatedWhenTracesStartAndStop() {
final AtomicInteger cacheUpdateCallCount = new AtomicInteger(0);
- mCacheUpdater = cacheUpdateCallCount::incrementAndGet;
+ sCacheUpdater = cacheUpdateCallCount::incrementAndGet;
- PerfettoTraceMonitor traceMonitor1 =
- PerfettoTraceMonitor.newBuilder().enableProtoLog(true,
- List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride(
- TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.WARN,
- false)))
- .build();
+ PerfettoTraceMonitor traceMonitor1 = PerfettoTraceMonitor.newBuilder()
+ .enableProtoLog(true,
+ List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride(
+ TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.WARN,
+ false)), TEST_PROTOLOG_DATASOURCE_NAME
+ ).build();
PerfettoTraceMonitor traceMonitor2 =
PerfettoTraceMonitor.newBuilder().enableProtoLog(true,
List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride(
TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.DEBUG,
- false)))
+ false)), TEST_PROTOLOG_DATASOURCE_NAME)
.build();
Truth.assertThat(cacheUpdateCallCount.get()).isEqualTo(0);
@@ -619,107 +654,107 @@
@Test
public void isEnabledUpdatesBasedOnRunningTraces() {
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
.isFalse();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
.isFalse();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
.isFalse();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
.isFalse();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
.isFalse();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF)).isFalse();
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF)).isFalse();
PerfettoTraceMonitor traceMonitor1 =
PerfettoTraceMonitor.newBuilder().enableProtoLog(true,
List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride(
TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.WARN,
- false)))
+ false)), TEST_PROTOLOG_DATASOURCE_NAME)
.build();
PerfettoTraceMonitor traceMonitor2 =
PerfettoTraceMonitor.newBuilder().enableProtoLog(true,
List.of(new PerfettoTraceMonitor.Builder.ProtoLogGroupOverride(
TestProtoLogGroup.TEST_GROUP.toString(), LogLevel.DEBUG,
- false)))
+ false)), TEST_PROTOLOG_DATASOURCE_NAME)
.build();
try {
traceMonitor1.start();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
.isFalse();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
.isFalse();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
.isFalse();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
.isTrue();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
.isTrue();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
.isTrue();
try {
traceMonitor2.start();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
.isTrue();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP,
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP,
LogLevel.VERBOSE)).isTrue();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
.isTrue();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
.isTrue();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
.isTrue();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
.isTrue();
} finally {
traceMonitor2.stop(mWriter);
}
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
.isFalse();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
.isFalse();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
.isFalse();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
.isTrue();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
.isTrue();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
.isTrue();
} finally {
traceMonitor1.stop(mWriter);
}
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.DEBUG))
.isFalse();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.VERBOSE))
.isFalse();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.INFO))
.isFalse();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WARN))
.isFalse();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.ERROR))
.isFalse();
- Truth.assertThat(mProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
+ Truth.assertThat(sProtoLog.isEnabled(TestProtoLogGroup.TEST_GROUP, LogLevel.WTF))
.isFalse();
}
@Test
public void supportsNullString() throws IOException {
- PerfettoTraceMonitor traceMonitor =
- PerfettoTraceMonitor.newBuilder().enableProtoLog(true)
- .build();
+ PerfettoTraceMonitor traceMonitor = PerfettoTraceMonitor.newBuilder()
+ .enableProtoLog(true, List.of(), TEST_PROTOLOG_DATASOURCE_NAME)
+ .build();
try {
traceMonitor.start();
- mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP,
+ sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP,
"My test null string: %s", (Object) null);
} finally {
traceMonitor.stop(mWriter);
@@ -735,14 +770,14 @@
@Test
public void supportNullParams() throws IOException {
- PerfettoTraceMonitor traceMonitor =
- PerfettoTraceMonitor.newBuilder().enableProtoLog(true)
- .build();
+ PerfettoTraceMonitor traceMonitor = PerfettoTraceMonitor.newBuilder()
+ .enableProtoLog(true, List.of(), TEST_PROTOLOG_DATASOURCE_NAME)
+ .build();
try {
traceMonitor.start();
- mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP,
+ sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP,
"My null args: %d, %f, %b", null, null, null);
} finally {
traceMonitor.stop(mWriter);
@@ -753,18 +788,18 @@
Truth.assertThat(protolog.messages).hasSize(1);
Truth.assertThat(protolog.messages.get(0).getMessage())
- .isEqualTo("My null args: 0, 0, false");
+ .isEqualTo("My null args: 0, 0.000000, false");
}
@Test
public void handlesConcurrentTracingSessions() throws IOException {
- PerfettoTraceMonitor traceMonitor1 =
- PerfettoTraceMonitor.newBuilder().enableProtoLog(true)
- .build();
+ PerfettoTraceMonitor traceMonitor1 = PerfettoTraceMonitor.newBuilder()
+ .enableProtoLog(true, List.of(), TEST_PROTOLOG_DATASOURCE_NAME)
+ .build();
- PerfettoTraceMonitor traceMonitor2 =
- PerfettoTraceMonitor.newBuilder().enableProtoLog(true)
- .build();
+ PerfettoTraceMonitor traceMonitor2 = PerfettoTraceMonitor.newBuilder()
+ .enableProtoLog(true, List.of(), TEST_PROTOLOG_DATASOURCE_NAME)
+ .build();
final ResultWriter writer2 = new ResultWriter()
.forScenario(new ScenarioBuilder()
@@ -776,7 +811,7 @@
traceMonitor1.start();
traceMonitor2.start();
- mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
+ sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 1,
LogDataType.BOOLEAN, new Object[]{true});
} finally {
traceMonitor1.stop(mWriter);
@@ -800,16 +835,17 @@
@Test
public void usesDefaultLogFromLevel() throws IOException {
- PerfettoTraceMonitor traceMonitor =
- PerfettoTraceMonitor.newBuilder().enableProtoLog(LogLevel.WARN).build();
+ PerfettoTraceMonitor traceMonitor = PerfettoTraceMonitor.newBuilder()
+ .enableProtoLog(LogLevel.WARN, List.of(), TEST_PROTOLOG_DATASOURCE_NAME)
+ .build();
try {
traceMonitor.start();
- mProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP,
- "This message should not be logged");
- mProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP,
- "This message should logged %d", 123);
- mProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP,
- "This message should also be logged %d", 567);
+ sProtoLog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP,
+ "This message should not be logged");
+ sProtoLog.log(LogLevel.WARN, TestProtoLogGroup.TEST_GROUP,
+ "This message should be logged %d", 123);
+ sProtoLog.log(LogLevel.ERROR, TestProtoLogGroup.TEST_GROUP,
+ "This message should also be logged %d", 567);
} finally {
traceMonitor.stop(mWriter);
}
@@ -822,7 +858,7 @@
Truth.assertThat(protolog.messages.get(0).getLevel())
.isEqualTo(LogLevel.WARN);
Truth.assertThat(protolog.messages.get(0).getMessage())
- .isEqualTo("This message should logged 123");
+ .isEqualTo("This message should be logged 123");
Truth.assertThat(protolog.messages.get(1).getLevel())
.isEqualTo(LogLevel.ERROR);
@@ -830,6 +866,19 @@
.isEqualTo("This message should also be logged 567");
}
+ @Test
+ public void throwsOnLogToLogcatForProcessedMessageMissingLoadedDefinition() {
+ TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true);
+ var protolog = new PerfettoProtoLogImpl(TestProtoLogGroup.values());
+
+ var exception = assertThrows(RuntimeException.class, () -> {
+ protolog.log(LogLevel.DEBUG, TestProtoLogGroup.TEST_GROUP, 123, 0, new Object[0]);
+ });
+
+ Truth.assertThat(exception).hasMessageThat()
+ .contains("Failed to get log message with hash 123");
+ }
+
private enum TestProtoLogGroup implements IProtoLogGroup {
TEST_GROUP(true, true, false, "TEST_TAG");
diff --git a/tests/TrustTests/Android.bp b/tests/TrustTests/Android.bp
index 4e75a1d..8888b32 100644
--- a/tests/TrustTests/Android.bp
+++ b/tests/TrustTests/Android.bp
@@ -40,3 +40,10 @@
platform_apis: true,
certificate: "platform",
}
+
+test_module_config {
+ name: "TrustTests_trust_test",
+ base: "TrustTests",
+ test_suites: ["device-tests"],
+ include_filters: ["android.trust.test"],
+}
diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
index 887630b..b5cc553 100644
--- a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
@@ -59,7 +59,6 @@
import android.os.ParcelUuid;
import android.os.PersistableBundle;
import android.os.test.TestLooper;
-import android.platform.test.flag.junit.SetFlagsRule;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -73,10 +72,7 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.telephony.flags.Flags;
-
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -133,8 +129,6 @@
TEST_SUBID_TO_CARRIER_CONFIG_MAP = Collections.unmodifiableMap(subIdToCarrierConfigMap);
}
- @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
-
@NonNull private final Context mContext;
@NonNull private final TestLooper mTestLooper;
@@ -193,7 +187,6 @@
@Before
public void setUp() throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_FIX_CRASH_ON_GETTING_CONFIG_WHEN_PHONE_IS_GONE);
doReturn(2).when(mTelephonyManager).getActiveModemCount();
mCallback = mock(TelephonySubscriptionTrackerCallback.class);
diff --git a/tools/hoststubgen/hoststubgen/Android.bp b/tools/hoststubgen/hoststubgen/Android.bp
index 682adbc..ea77b8d 100644
--- a/tools/hoststubgen/hoststubgen/Android.bp
+++ b/tools/hoststubgen/hoststubgen/Android.bp
@@ -118,7 +118,6 @@
java_test_host {
name: "hoststubgentest",
- // main_class: "com.android.hoststubgen.Main",
srcs: ["test/**/*.kt"],
static_libs: [
"hoststubgen",
@@ -143,8 +142,7 @@
// "--policy-override-file $(location framework-policy-override.txt) " +
"@$(location :hoststubgen-standard-options) " +
- "--out-stub-jar $(location host_stub.jar) " +
- "--out-impl-jar $(location host_impl.jar) " +
+ "--out-jar $(location host.jar) " +
// "--keep-all-classes " + // Used it for an experiment. See KeepAllClassesFilter.
"--gen-keep-all-file $(location hoststubgen_keep_all.txt) " +
@@ -159,10 +157,8 @@
srcs: [
":hoststubgen-standard-options",
],
- // Create two jar files.
out: [
- "host_stub.jar",
- "host_impl.jar",
+ "host.jar",
// Following files are created just as FYI.
"hoststubgen_keep_all.txt",
diff --git a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodNativeSubstitutionClass.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRedirect.java
similarity index 76%
copy from ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodNativeSubstitutionClass.java
copy to tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRedirect.java
index 4b9cf85..bc9471b 100644
--- a/ravenwood/annotations-src/android/ravenwood/annotation/RavenwoodNativeSubstitutionClass.java
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRedirect.java
@@ -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.
@@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.ravenwood.annotation;
+package android.hosttest.annotation;
-import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.ElementType.METHOD;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -24,13 +24,9 @@
/**
* THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
* QUESTIONS ABOUT IT.
- *
- * TODO: Javadoc
- *
* @hide
*/
-@Target({TYPE})
+@Target({METHOD})
@Retention(RetentionPolicy.CLASS)
-public @interface RavenwoodNativeSubstitutionClass {
- String value();
+public @interface HostSideTestRedirect {
}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRedirectionClass.java
similarity index 95%
rename from tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java
rename to tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRedirectionClass.java
index 9c81383..28ad236 100644
--- a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestNativeSubstitutionClass.java
+++ b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestRedirectionClass.java
@@ -30,6 +30,6 @@
*/
@Target({TYPE})
@Retention(RetentionPolicy.CLASS)
-public @interface HostSideTestNativeSubstitutionClass {
+public @interface HostSideTestRedirectionClass {
String value();
}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java
deleted file mode 100644
index cabdfe0..0000000
--- a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestStub.java
+++ /dev/null
@@ -1,43 +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 android.hosttest.annotation;
-
-import static java.lang.annotation.ElementType.CONSTRUCTOR;
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.TYPE;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
- * QUESTIONS ABOUT IT.
- *
- * Mark a class, field or a method as "Stub", meaning tests can see the APIs.
- * When applied to a class, it will _not_ affect the visibility of its members. They need to be
- * individually marked.
- *
- * <p>In order to expose a class and all its members, use {@link HostSideTestWholeClassStub}
- * instead.
- *
- * @hide
- */
-@Target({TYPE, FIELD, METHOD, CONSTRUCTOR})
-@Retention(RetentionPolicy.CLASS)
-public @interface HostSideTestStub {
-}
diff --git a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java b/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java
deleted file mode 100644
index 1824f6f..0000000
--- a/tools/hoststubgen/hoststubgen/annotations-src/android/hosttest/annotation/HostSideTestWholeClassStub.java
+++ /dev/null
@@ -1,35 +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 android.hosttest.annotation;
-
-import static java.lang.annotation.ElementType.TYPE;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * THIS ANNOTATION IS EXPERIMENTAL. REACH OUT TO g/ravenwood BEFORE USING IT, OR YOU HAVE ANY
- * QUESTIONS ABOUT IT.
- *
- * Same as {@link HostSideTestStub} but it'll change the visibility of all its members too.
- *
- * @hide
- */
-@Target({TYPE})
-@Retention(RetentionPolicy.CLASS)
-public @interface HostSideTestWholeClassStub {
-}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenKeptInStub.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenKeptInStub.java
deleted file mode 100644
index 12b9875..0000000
--- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenKeptInStub.java
+++ /dev/null
@@ -1,38 +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.hoststubgen.hosthelper;
-
-import static java.lang.annotation.ElementType.CONSTRUCTOR;
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.TYPE;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation injected to all classes/methods/fields that are kept in the "stub" jar.
- *
- * All items in the stub jar are automatically kept in the impl jar as well, so
- * the items with this annotation will all have {@link HostStubGenKeptInImpl} too.
- */
-@Target({TYPE, METHOD, CONSTRUCTOR, FIELD})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface HostStubGenKeptInStub {
- String CLASS_INTERNAL_NAME = HostTestUtils.getInternalName(HostStubGenKeptInStub.class);
- String CLASS_DESCRIPTOR = "L" + CLASS_INTERNAL_NAME + ";";
-}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsIgnore.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsIgnore.java
index cb50404..b017103 100644
--- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsIgnore.java
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsIgnore.java
@@ -23,8 +23,6 @@
/**
* Annotation injected to all methods processed as "ignore".
- *
- * (This annotation is only added in the impl jar, but not the stub jar)
*/
@Target({METHOD})
@Retention(RetentionPolicy.RUNTIME)
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenKeptInImpl.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsKeep.java
similarity index 92%
rename from tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenKeptInImpl.java
rename to tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsKeep.java
index 2cc500f..18ef1ba 100644
--- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenKeptInImpl.java
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsKeep.java
@@ -25,11 +25,11 @@
import java.lang.annotation.Target;
/**
- * Annotation injected to all classes/methods/fields that are kept in the "impl" jar.
+ * Annotation injected to all classes/methods/fields that are kept in the processes jar.
*/
@Target({TYPE, METHOD, CONSTRUCTOR, FIELD})
@Retention(RetentionPolicy.RUNTIME)
-public @interface HostStubGenKeptInImpl {
- String CLASS_INTERNAL_NAME = HostTestUtils.getInternalName(HostStubGenKeptInImpl.class);
+public @interface HostStubGenProcessedAsKeep {
+ String CLASS_INTERNAL_NAME = HostTestUtils.getInternalName(HostStubGenProcessedAsKeep.class);
String CLASS_DESCRIPTOR = "L" + CLASS_INTERNAL_NAME + ";";
}
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsSubstitute.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsSubstitute.java
index cfa4896..99e38c0 100644
--- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsSubstitute.java
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsSubstitute.java
@@ -26,8 +26,6 @@
/**
* Annotation injected to all methods that are processed as "substitute".
- *
- * (This annotation is only added in the impl jar, but not the stub jar)
*/
@Target({TYPE, METHOD, CONSTRUCTOR, FIELD})
@Retention(RetentionPolicy.RUNTIME)
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsThrow.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsThrow.java
index 0d2da11..4933cf8 100644
--- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsThrow.java
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostStubGenProcessedAsThrow.java
@@ -23,8 +23,6 @@
/**
* Annotation injected to all methods that are processed as "throw".
- *
- * (This annotation is only added in the impl jar, but not the stub jar)
*/
@Target({METHOD})
@Retention(RetentionPolicy.RUNTIME)
diff --git a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java
index 60eb47ee..78fd8f7 100644
--- a/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java
+++ b/tools/hoststubgen/hoststubgen/helper-runtime-src/com/android/hoststubgen/hosthelper/HostTestUtils.java
@@ -16,12 +16,8 @@
package com.android.hoststubgen.hosthelper;
import java.io.PrintStream;
-import java.lang.StackWalker.Option;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
-import java.util.HashMap;
-
-import javax.annotation.concurrent.GuardedBy;
/**
* Utilities used in the host side test environment.
@@ -101,68 +97,6 @@
+ methodName + methodDescriptor);
}
- private static final StackWalker sStackWalker =
- StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
-
- /**
- * Return a {@link StackWalker} that supports {@link StackWalker#getCallerClass()}.
- */
- public static StackWalker getStackWalker() {
- return sStackWalker;
- }
-
- /**
- * Cache used by {@link #isClassAllowedToCallNonStubMethods}.
- */
- @GuardedBy("sAllowedClasses")
- private static final HashMap<Class, Boolean> sAllowedClasses = new HashMap();
-
- /**
- * Return true if a given class is allowed to access non-stub methods -- that is, if the class
- * is in the hoststubgen generated JARs. (not in the test jar.)
- */
- private static boolean isClassAllowedToCallNonStubMethods(Class<?> clazz) {
- synchronized (sAllowedClasses) {
- var cached = sAllowedClasses.get(clazz);
- if (cached != null) {
- return cached;
- }
- }
- // All processed classes have this annotation.
- var allowed = clazz.getAnnotation(HostStubGenKeptInImpl.class) != null;
-
- // Java classes should be able to access any methods. (via callbacks, etc.)
- if (!allowed) {
- if (clazz.getPackageName().startsWith("java.")
- || clazz.getPackageName().startsWith("javax.")) {
- allowed = true;
- }
- }
- synchronized (sAllowedClasses) {
- sAllowedClasses.put(clazz, allowed);
- }
- return allowed;
- }
-
- /**
- * Called when non-stub methods are called. We do a host-unsupported method direct call check
- * in here.
- */
- public static void onNonStubMethodCalled(
- String methodClass,
- String methodName,
- String methodDescriptor,
- Class<?> callerClass) {
- if (SKIP_NON_STUB_METHOD_CHECK) {
- return;
- }
- if (isClassAllowedToCallNonStubMethods(callerClass)) {
- return; // Generated class is allowed to call framework class.
- }
- logPrintStream.println("! " + methodClass + "." + methodName + methodDescriptor
- + " called by " + callerClass.getCanonicalName());
- }
-
/**
* Called when any top level class (not nested classes) in the impl jar is loaded.
*
diff --git a/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt b/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt
index c371b5d..eba8e62 100644
--- a/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt
+++ b/tools/hoststubgen/hoststubgen/hoststubgen-standard-options.txt
@@ -3,8 +3,6 @@
--debug
# Uncomment below lines to enable each feature.
---enable-non-stub-method-check
-# --no-non-stub-method-check
#--default-method-call-hook
# com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
@@ -13,15 +11,10 @@
# Standard annotations.
# Note, each line is a single argument, so we need newlines after each `--xxx-annotation`.
---stub-annotation
- android.hosttest.annotation.HostSideTestStub
--keep-annotation
android.hosttest.annotation.HostSideTestKeep
---stub-class-annotation
- android.hosttest.annotation.HostSideTestWholeClassStub
-
--keep-class-annotation
android.hosttest.annotation.HostSideTestWholeClassKeep
@@ -34,8 +27,11 @@
--substitute-annotation
android.hosttest.annotation.HostSideTestSubstitute
---native-substitute-annotation
- android.hosttest.annotation.HostSideTestNativeSubstitutionClass
+--redirect-annotation
+ android.hosttest.annotation.HostSideTestRedirect
+
+--redirection-class-annotation
+ android.hosttest.annotation.HostSideTestRedirectionClass
--class-load-hook-annotation
android.hosttest.annotation.HostSideTestClassLoadHook
diff --git a/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh b/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh
index 5c5421a..084448d 100755
--- a/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh
+++ b/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh
@@ -43,9 +43,8 @@
cleanup_temp
-JAR=hoststubgen-test-tiny-framework.jar
-STUB=$TEMP/stub.jar
-IMPL=$TEMP/impl.jar
+INJAR=hoststubgen-test-tiny-framework.jar
+OUTJAR=$TEMP/host.jar
ANNOTATION_FILTER=$TEMP/annotation-filter.txt
@@ -81,27 +80,18 @@
cat $ANNOTATION_FILTER
fi
- local stub_arg=""
- local impl_arg=""
+ local out_arg=""
- if [[ "$STUB" != "" ]] ; then
- stub_arg="--out-stub-jar $STUB"
- fi
- if [[ "$IMPL" != "" ]] ; then
- impl_arg="--out-impl-jar $IMPL"
+ if [[ "$OUTJAR" != "" ]] ; then
+ out_arg="--out-jar $OUTJAR"
fi
hoststubgen \
--debug \
- --in-jar $JAR \
- $stub_arg \
- $impl_arg \
- --stub-annotation \
- android.hosttest.annotation.HostSideTestStub \
+ --in-jar $INJAR \
+ $out_arg \
--keep-annotation \
android.hosttest.annotation.HostSideTestKeep \
- --stub-class-annotation \
- android.hosttest.annotation.HostSideTestWholeClassStub \
--keep-class-annotation \
android.hosttest.annotation.HostSideTestWholeClassKeep \
--throw-annotation \
@@ -110,8 +100,10 @@
android.hosttest.annotation.HostSideTestRemove \
--substitute-annotation \
android.hosttest.annotation.HostSideTestSubstitute \
- --native-substitute-annotation \
- android.hosttest.annotation.HostSideTestNativeSubstitutionClass \
+ --redirect-annotation \
+ android.hosttest.annotation.HostSideTestRedirect \
+ --redirection-class-annotation \
+ android.hosttest.annotation.HostSideTestRedirectionClass \
--class-load-hook-annotation \
android.hosttest.annotation.HostSideTestClassLoadHook \
--keep-static-initializer-annotation \
@@ -225,11 +217,7 @@
* # All other classes allowed
"
-STUB="" run_hoststubgen_for_success "No stub generation" ""
-
-IMPL="" run_hoststubgen_for_success "No impl generation" ""
-
-STUB="" IMPL="" run_hoststubgen_for_success "No stub, no impl generation" ""
+OUTJAR="" run_hoststubgen_for_success "No output generation" ""
EXTRA_ARGS="--in-jar abc" run_hoststubgen_for_failure "Duplicate arg" \
"Duplicate or conflicting argument found: --in-jar" \
@@ -237,4 +225,4 @@
echo "All tests passed"
-exit 0
\ No newline at end of file
+exit 0
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
index 7b08678..34aaaa9 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
@@ -24,19 +24,14 @@
import com.android.hoststubgen.filters.FilterPolicy
import com.android.hoststubgen.filters.FilterRemapper
import com.android.hoststubgen.filters.ImplicitOutputFilter
+import com.android.hoststubgen.filters.KeepNativeFilter
import com.android.hoststubgen.filters.OutputFilter
-import com.android.hoststubgen.filters.StubIntersectingFilter
+import com.android.hoststubgen.filters.SanitizationFilter
import com.android.hoststubgen.filters.createFilterFromTextPolicyFile
import com.android.hoststubgen.filters.printAsTextPolicy
import com.android.hoststubgen.utils.ClassFilter
import com.android.hoststubgen.visitors.BaseAdapter
import com.android.hoststubgen.visitors.PackageRedirectRemapper
-import org.objectweb.asm.ClassReader
-import org.objectweb.asm.ClassVisitor
-import org.objectweb.asm.ClassWriter
-import org.objectweb.asm.commons.ClassRemapper
-import org.objectweb.asm.commons.Remapper
-import org.objectweb.asm.util.CheckClassAdapter
import java.io.BufferedInputStream
import java.io.BufferedOutputStream
import java.io.FileOutputStream
@@ -46,6 +41,12 @@
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
import java.util.zip.ZipOutputStream
+import org.objectweb.asm.ClassReader
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.ClassWriter
+import org.objectweb.asm.commons.ClassRemapper
+import org.objectweb.asm.commons.Remapper
+import org.objectweb.asm.util.CheckClassAdapter
/**
* Actual main class.
@@ -82,17 +83,16 @@
// Transform the jar.
convert(
- options.inJar.get,
- options.outStubJar.get,
- options.outImplJar.get,
- filter,
- options.enableClassChecker.get,
- allClasses,
- errors,
- stats,
- filterRemapper,
- options.numShards.get,
- options.shard.get,
+ options.inJar.get,
+ options.outJar.get,
+ filter,
+ options.enableClassChecker.get,
+ allClasses,
+ errors,
+ stats,
+ filterRemapper,
+ options.numShards.get,
+ options.shard.get,
)
// Dump statistics, if specified.
@@ -117,10 +117,10 @@
* jars, and "how". (e.g. with substitution?)
*/
private fun buildFilter(
- errors: HostStubGenErrors,
- allClasses: ClassNodes,
- options: HostStubGenOptions,
- ): OutputFilter {
+ errors: HostStubGenErrors,
+ allClasses: ClassNodes,
+ options: HostStubGenOptions,
+ ): OutputFilter {
// We build a "chain" of multiple filters here.
//
// The filters are build in from "inside", meaning the first filter created here is
@@ -134,6 +134,9 @@
// The first filter is for the default policy from the command line options.
var filter: OutputFilter = ConstantFilter(options.defaultPolicy.get, "default-by-options")
+ // Next, we build a filter that preserves all native methods by default
+ filter = KeepNativeFilter(allClasses, filter)
+
// Next, we need a filter that resolves "class-wide" policies.
// This is used when a member (methods, fields, nested classes) don't get any polices
// from upper filters. e.g. when a method has no annotations, then this filter will apply
@@ -159,18 +162,17 @@
filter = AnnotationBasedFilter(
errors,
allClasses,
- options.stubAnnotations,
options.keepAnnotations,
- options.stubClassAnnotations,
options.keepClassAnnotations,
options.throwAnnotations,
options.removeAnnotations,
options.substituteAnnotations,
- options.nativeSubstituteAnnotations,
+ options.redirectAnnotations,
+ options.redirectionClassAnnotations,
options.classLoadHookAnnotations,
options.keepStaticInitializerAnnotations,
annotationAllowedClassesFilter,
- filter,
+ filter
)
// Next, "text based" filter, which allows to override polices without touching
@@ -179,50 +181,31 @@
filter = createFilterFromTextPolicyFile(it, allClasses, filter)
}
- // If `--intersect-stub-jar` is provided, load from these jar files too.
- // We use this to restrict stub APIs to public/system/test APIs,
- // by intersecting with a stub jar file created by metalava.
- if (options.intersectStubJars.size > 0) {
- val intersectingJars = loadIntersectingJars(options.intersectStubJars)
-
- filter = StubIntersectingFilter(errors, intersectingJars, filter)
- }
-
// Apply the implicit filter.
filter = ImplicitOutputFilter(errors, allClasses, filter)
+ // Add a final sanitization step.
+ filter = SanitizationFilter(errors, allClasses, filter)
+
return filter
}
/**
- * Load jar files specified with "--intersect-stub-jar".
- */
- private fun loadIntersectingJars(filenames: Set<String>): Map<String, ClassNodes> {
- val intersectingJars = mutableMapOf<String, ClassNodes>()
-
- filenames.forEach { filename ->
- intersectingJars[filename] = ClassNodes.loadClassStructures(filename)
- }
- return intersectingJars
- }
-
- /**
* Convert a JAR file into "stub" and "impl" JAR files.
*/
private fun convert(
- inJar: String,
- outStubJar: String?,
- outImplJar: String?,
- filter: OutputFilter,
- enableChecker: Boolean,
- classes: ClassNodes,
- errors: HostStubGenErrors,
- stats: HostStubGenStats,
- remapper: Remapper?,
- numShards: Int,
- shard: Int,
- ) {
- log.i("Converting %s into [stub: %s, impl: %s] ...", inJar, outStubJar, outImplJar)
+ inJar: String,
+ outJar: String?,
+ filter: OutputFilter,
+ enableChecker: Boolean,
+ classes: ClassNodes,
+ errors: HostStubGenErrors,
+ stats: HostStubGenStats,
+ remapper: Remapper?,
+ numShards: Int,
+ shard: Int
+ ) {
+ log.i("Converting %s into %s ...", inJar, outJar)
log.i("ASM CheckClassAdapter is %s", if (enableChecker) "enabled" else "disabled")
log.iTime("Transforming jar") {
@@ -240,29 +223,26 @@
val shardStart = numItems * shard / numShards
val shardNextStart = numItems * (shard + 1) / numShards
- maybeWithZipOutputStream(outStubJar) { stubOutStream ->
- maybeWithZipOutputStream(outImplJar) { implOutStream ->
- val inEntries = inZip.entries()
- while (inEntries.hasMoreElements()) {
- val entry = inEntries.nextElement()
- val inShard = (shardStart <= itemIndex)
- && (itemIndex < shardNextStart)
- itemIndex++
- if (!inShard) {
- continue
- }
- convertSingleEntry(
- inZip, entry, stubOutStream, implOutStream,
- filter, packageRedirector, remapper,
- enableChecker, classes, errors, stats
- )
- numItemsProcessed++
+ maybeWithZipOutputStream(outJar) { outStream ->
+ val inEntries = inZip.entries()
+ while (inEntries.hasMoreElements()) {
+ val entry = inEntries.nextElement()
+ val inShard = (shardStart <= itemIndex)
+ && (itemIndex < shardNextStart)
+ itemIndex++
+ if (!inShard) {
+ continue
}
- log.i("Converted all entries.")
+ convertSingleEntry(
+ inZip, entry, outStream, filter,
+ packageRedirector, remapper, enableChecker,
+ classes, errors, stats
+ )
+ numItemsProcessed++
}
+ log.i("Converted all entries.")
}
- outStubJar?.let { log.i("Created stub: $it") }
- outImplJar?.let { log.i("Created impl: $it") }
+ outJar?.let { log.i("Created: $it") }
}
}
log.i("%d / %d item(s) processed.", numItemsProcessed, numItems)
@@ -280,18 +260,17 @@
* Convert a single ZIP entry, which may or may not be a class file.
*/
private fun convertSingleEntry(
- inZip: ZipFile,
- entry: ZipEntry,
- stubOutStream: ZipOutputStream?,
- implOutStream: ZipOutputStream?,
- filter: OutputFilter,
- packageRedirector: PackageRedirectRemapper,
- remapper: Remapper?,
- enableChecker: Boolean,
- classes: ClassNodes,
- errors: HostStubGenErrors,
- stats: HostStubGenStats,
- ) {
+ inZip: ZipFile,
+ entry: ZipEntry,
+ outStream: ZipOutputStream?,
+ filter: OutputFilter,
+ packageRedirector: PackageRedirectRemapper,
+ remapper: Remapper?,
+ enableChecker: Boolean,
+ classes: ClassNodes,
+ errors: HostStubGenErrors,
+ stats: HostStubGenStats
+ ) {
log.d("Entry: %s", entry.name)
log.withIndent {
val name = entry.name
@@ -303,8 +282,10 @@
// If it's a class, convert it.
if (name.endsWith(".class")) {
- processSingleClass(inZip, entry, stubOutStream, implOutStream, filter,
- packageRedirector, remapper, enableChecker, classes, errors, stats)
+ processSingleClass(
+ inZip, entry, outStream, filter, packageRedirector,
+ remapper, enableChecker, classes, errors, stats
+ )
return
}
@@ -312,17 +293,14 @@
// - *.uau seems to contain hidden API information.
// - *_compat_config.xml is also about compat-framework.
- if (name.endsWith(".uau") ||
- name.endsWith("_compat_config.xml")) {
+ if (name.endsWith(".uau") || name.endsWith("_compat_config.xml")) {
log.d("Not needed: %s", entry.name)
return
}
// Unknown type, we just copy it to both output zip files.
- // TODO: We probably shouldn't do it for stub jar?
log.v("Copying: %s", entry.name)
- stubOutStream?.let { copyZipEntry(inZip, entry, it) }
- implOutStream?.let { copyZipEntry(inZip, entry, it) }
+ outStream?.let { copyZipEntry(inZip, entry, it) }
}
}
@@ -330,10 +308,10 @@
* Copy a single ZIP entry to the output.
*/
private fun copyZipEntry(
- inZip: ZipFile,
- entry: ZipEntry,
- out: ZipOutputStream,
- ) {
+ inZip: ZipFile,
+ entry: ZipEntry,
+ out: ZipOutputStream,
+ ) {
// TODO: It seems like copying entries this way is _very_ slow,
// even with out.setLevel(0). Look for other ways to do it.
@@ -350,18 +328,17 @@
* Convert a single class to "stub" and "impl".
*/
private fun processSingleClass(
- inZip: ZipFile,
- entry: ZipEntry,
- stubOutStream: ZipOutputStream?,
- implOutStream: ZipOutputStream?,
- filter: OutputFilter,
- packageRedirector: PackageRedirectRemapper,
- remapper: Remapper?,
- enableChecker: Boolean,
- classes: ClassNodes,
- errors: HostStubGenErrors,
- stats: HostStubGenStats,
- ) {
+ inZip: ZipFile,
+ entry: ZipEntry,
+ outStream: ZipOutputStream?,
+ filter: OutputFilter,
+ packageRedirector: PackageRedirectRemapper,
+ remapper: Remapper?,
+ enableChecker: Boolean,
+ classes: ClassNodes,
+ errors: HostStubGenErrors,
+ stats: HostStubGenStats
+ ) {
val classInternalName = entry.name.replaceFirst("\\.class$".toRegex(), "")
val classPolicy = filter.getPolicyForClass(classInternalName)
if (classPolicy.policy == FilterPolicy.Remove) {
@@ -373,33 +350,22 @@
remapper?.mapType(classInternalName)?.let { remappedName ->
if (remappedName != classInternalName) {
log.d("Renaming class file: %s -> %s", classInternalName, remappedName)
- newName = remappedName + ".class"
+ newName = "$remappedName.class"
}
}
- // Generate stub first.
- if (stubOutStream != null && classPolicy.policy.needsInStub) {
- log.v("Creating stub class: %s Policy: %s", classInternalName, classPolicy)
+
+ if (outStream != null) {
+ log.v("Creating class: %s Policy: %s", classInternalName, classPolicy)
log.withIndent {
BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
val newEntry = ZipEntry(newName)
- stubOutStream.putNextEntry(newEntry)
- convertClass(classInternalName, /*forImpl=*/false, bis,
- stubOutStream, filter, packageRedirector, remapper,
- enableChecker, classes, errors, null)
- stubOutStream.closeEntry()
- }
- }
- }
- if (implOutStream != null && classPolicy.policy.needsInImpl) {
- log.v("Creating impl class: %s Policy: %s", classInternalName, classPolicy)
- log.withIndent {
- BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
- val newEntry = ZipEntry(newName)
- implOutStream.putNextEntry(newEntry)
- convertClass(classInternalName, /*forImpl=*/true, bis,
- implOutStream, filter, packageRedirector, remapper,
- enableChecker, classes, errors, stats)
- implOutStream.closeEntry()
+ outStream.putNextEntry(newEntry)
+ convertClass(
+ classInternalName, bis,
+ outStream, filter, packageRedirector, remapper,
+ enableChecker, classes, errors, stats
+ )
+ outStream.closeEntry()
}
}
}
@@ -409,18 +375,17 @@
* Convert a single class to either "stub" or "impl".
*/
private fun convertClass(
- classInternalName: String,
- forImpl: Boolean,
- input: InputStream,
- out: OutputStream,
- filter: OutputFilter,
- packageRedirector: PackageRedirectRemapper,
- remapper: Remapper?,
- enableChecker: Boolean,
- classes: ClassNodes,
- errors: HostStubGenErrors,
- stats: HostStubGenStats?,
- ) {
+ classInternalName: String,
+ input: InputStream,
+ out: OutputStream,
+ filter: OutputFilter,
+ packageRedirector: PackageRedirectRemapper,
+ remapper: Remapper?,
+ enableChecker: Boolean,
+ classes: ClassNodes,
+ errors: HostStubGenErrors,
+ stats: HostStubGenStats?
+ ) {
val cr = ClassReader(input)
// COMPUTE_FRAMES wouldn't be happy if code uses
@@ -439,14 +404,15 @@
}
val visitorOptions = BaseAdapter.Options(
- enablePreTrace = options.enablePreTrace.get,
- enablePostTrace = options.enablePostTrace.get,
- enableNonStubMethodCallDetection = options.enableNonStubMethodCallDetection.get,
- errors = errors,
- stats = stats,
+ errors = errors,
+ stats = stats,
+ enablePreTrace = options.enablePreTrace.get,
+ enablePostTrace = options.enablePostTrace.get,
)
- outVisitor = BaseAdapter.getVisitor(classInternalName, classes, outVisitor, filter,
- packageRedirector, remapper, forImpl, visitorOptions)
+ outVisitor = BaseAdapter.getVisitor(
+ classInternalName, classes, outVisitor, filter,
+ packageRedirector, visitorOptions
+ )
cr.accept(outVisitor, ClassReader.EXPAND_FRAMES)
val data = cw.toByteArray()
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
index f88b107..057a52c 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
@@ -74,25 +74,21 @@
/** Input jar file*/
var inJar: SetOnce<String> = SetOnce(""),
- /** Output stub jar file */
- var outStubJar: SetOnce<String?> = SetOnce(null),
-
- /** Output implementation jar file */
- var outImplJar: SetOnce<String?> = SetOnce(null),
+ /** Output jar file */
+ var outJar: SetOnce<String?> = SetOnce(null),
var inputJarDumpFile: SetOnce<String?> = SetOnce(null),
var inputJarAsKeepAllFile: SetOnce<String?> = SetOnce(null),
- var stubAnnotations: MutableSet<String> = mutableSetOf(),
var keepAnnotations: MutableSet<String> = mutableSetOf(),
var throwAnnotations: MutableSet<String> = mutableSetOf(),
var removeAnnotations: MutableSet<String> = mutableSetOf(),
- var stubClassAnnotations: MutableSet<String> = mutableSetOf(),
var keepClassAnnotations: MutableSet<String> = mutableSetOf(),
+ var redirectAnnotations: MutableSet<String> = mutableSetOf(),
var substituteAnnotations: MutableSet<String> = mutableSetOf(),
- var nativeSubstituteAnnotations: MutableSet<String> = mutableSetOf(),
+ var redirectionClassAnnotations: MutableSet<String> = mutableSetOf(),
var classLoadHookAnnotations: MutableSet<String> = mutableSetOf(),
var keepStaticInitializerAnnotations: MutableSet<String> = mutableSetOf(),
@@ -103,8 +99,6 @@
var defaultClassLoadHook: SetOnce<String?> = SetOnce(null),
var defaultMethodCallHook: SetOnce<String?> = SetOnce(null),
- var intersectStubJars: MutableSet<String> = mutableSetOf(),
-
var policyOverrideFile: SetOnce<String?> = SetOnce(null),
var defaultPolicy: SetOnce<FilterPolicy> = SetOnce(FilterPolicy.Remove),
@@ -115,8 +109,6 @@
var enablePreTrace: SetOnce<Boolean> = SetOnce(false),
var enablePostTrace: SetOnce<Boolean> = SetOnce(false),
- var enableNonStubMethodCallDetection: SetOnce<Boolean> = SetOnce(false),
-
var statsFile: SetOnce<String?> = SetOnce(null),
var apiListFile: SetOnce<String?> = SetOnce(null),
@@ -150,10 +142,7 @@
}
while (true) {
- val arg = ai.nextArgOptional()
- if (arg == null) {
- break
- }
+ val arg = ai.nextArgOptional() ?: break
// Define some shorthands...
fun nextArg(): String = ai.nextArgRequired(arg)
@@ -169,8 +158,9 @@
"-h", "--help" -> TODO("Help is not implemented yet")
"--in-jar" -> ret.inJar.set(nextArg()).ensureFileExists()
- "--out-stub-jar" -> ret.outStubJar.set(nextArg())
- "--out-impl-jar" -> ret.outImplJar.set(nextArg())
+ // We support both arguments because some AOSP dependencies
+ // still use the old argument
+ "--out-jar", "--out-impl-jar" -> ret.outJar.set(nextArg())
"--policy-override-file" ->
ret.policyOverrideFile.set(nextArg())!!.ensureFileExists()
@@ -181,17 +171,10 @@
"--default-remove" -> ret.defaultPolicy.set(FilterPolicy.Remove)
"--default-throw" -> ret.defaultPolicy.set(FilterPolicy.Throw)
"--default-keep" -> ret.defaultPolicy.set(FilterPolicy.Keep)
- "--default-stub" -> ret.defaultPolicy.set(FilterPolicy.Stub)
-
- "--stub-annotation" ->
- ret.stubAnnotations.addUniqueAnnotationArg()
"--keep-annotation" ->
ret.keepAnnotations.addUniqueAnnotationArg()
- "--stub-class-annotation" ->
- ret.stubClassAnnotations.addUniqueAnnotationArg()
-
"--keep-class-annotation" ->
ret.keepClassAnnotations.addUniqueAnnotationArg()
@@ -204,8 +187,11 @@
"--substitute-annotation" ->
ret.substituteAnnotations.addUniqueAnnotationArg()
- "--native-substitute-annotation" ->
- ret.nativeSubstituteAnnotations.addUniqueAnnotationArg()
+ "--redirect-annotation" ->
+ ret.redirectAnnotations.addUniqueAnnotationArg()
+
+ "--redirection-class-annotation" ->
+ ret.redirectionClassAnnotations.addUniqueAnnotationArg()
"--class-load-hook-annotation" ->
ret.classLoadHookAnnotations.addUniqueAnnotationArg()
@@ -225,9 +211,6 @@
"--default-method-call-hook" ->
ret.defaultMethodCallHook.set(nextArg())
- "--intersect-stub-jar" ->
- ret.intersectStubJars += nextArg().ensureFileExists()
-
"--gen-keep-all-file" ->
ret.inputJarAsKeepAllFile.set(nextArg())
@@ -241,12 +224,6 @@
"--enable-post-trace" -> ret.enablePostTrace.set(true)
"--no-post-trace" -> ret.enablePostTrace.set(false)
- "--enable-non-stub-method-check" ->
- ret.enableNonStubMethodCallDetection.set(true)
-
- "--no-non-stub-method-check" ->
- ret.enableNonStubMethodCallDetection.set(false)
-
"--gen-input-dump-file" -> ret.inputJarDumpFile.set(nextArg())
"--stats-file" -> ret.statsFile.set(nextArg())
@@ -273,9 +250,8 @@
if (!ret.inJar.isSet) {
throw ArgumentsException("Required option missing: --in-jar")
}
- if (!ret.outStubJar.isSet && !ret.outImplJar.isSet) {
- log.w("Neither --out-stub-jar nor --out-impl-jar is set." +
- " $executableName will not generate jar files.")
+ if (!ret.outJar.isSet) {
+ log.w("--out-jar is not set. $executableName will not generate jar files.")
}
if (ret.numShards.isSet != ret.shard.isSet) {
throw ArgumentsException("--num-shards and --shard-index must be used together")
@@ -287,11 +263,6 @@
}
}
- if (ret.enableNonStubMethodCallDetection.get) {
- log.w("--enable-non-stub-method-check is not fully implemented yet." +
- " See the todo in doesMethodNeedNonStubCallCheck().")
- }
-
return ret
}
}
@@ -300,32 +271,27 @@
return """
HostStubGenOptions{
inJar='$inJar',
- outStubJar='$outStubJar',
- outImplJar='$outImplJar',
+ outJar='$outJar',
inputJarDumpFile=$inputJarDumpFile,
inputJarAsKeepAllFile=$inputJarAsKeepAllFile,
- stubAnnotations=$stubAnnotations,
keepAnnotations=$keepAnnotations,
throwAnnotations=$throwAnnotations,
removeAnnotations=$removeAnnotations,
- stubClassAnnotations=$stubClassAnnotations,
keepClassAnnotations=$keepClassAnnotations,
substituteAnnotations=$substituteAnnotations,
- nativeSubstituteAnnotations=$nativeSubstituteAnnotations,
+ nativeSubstituteAnnotations=$redirectionClassAnnotations,
classLoadHookAnnotations=$classLoadHookAnnotations,
keepStaticInitializerAnnotations=$keepStaticInitializerAnnotations,
packageRedirects=$packageRedirects,
- $annotationAllowedClassesFile=$annotationAllowedClassesFile,
+ annotationAllowedClassesFile=$annotationAllowedClassesFile,
defaultClassLoadHook=$defaultClassLoadHook,
defaultMethodCallHook=$defaultMethodCallHook,
- intersectStubJars=$intersectStubJars,
policyOverrideFile=$policyOverrideFile,
defaultPolicy=$defaultPolicy,
cleanUpOnError=$cleanUpOnError,
enableClassChecker=$enableClassChecker,
enablePreTrace=$enablePreTrace,
enablePostTrace=$enablePostTrace,
- enableNonStubMethodCallDetection=$enableNonStubMethodCallDetection,
statsFile=$statsFile,
apiListFile=$apiListFile,
numShards=$numShards,
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
index 7dd4fdd..a02082d 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/asm/AsmUtils.kt
@@ -29,33 +29,24 @@
/** Name of the class initializer method. */
-val CLASS_INITIALIZER_NAME = "<clinit>"
+const val CLASS_INITIALIZER_NAME = "<clinit>"
/** Descriptor of the class initializer method. */
-val CLASS_INITIALIZER_DESC = "()V"
+const val CLASS_INITIALIZER_DESC = "()V"
/** Name of constructors. */
-val CTOR_NAME = "<init>"
+const val CTOR_NAME = "<init>"
/**
- * Find any of [anyAnnotations] from the list of visible / invisible annotations.
+ * Find any of [set] from the list of visible / invisible annotations.
*/
fun findAnyAnnotation(
- anyAnnotations: Set<String>,
- visibleAnnotations: List<AnnotationNode>?,
- invisibleAnnotations: List<AnnotationNode>?,
- ): AnnotationNode? {
- for (an in visibleAnnotations ?: emptyList()) {
- if (anyAnnotations.contains(an.desc)) {
- return an
- }
- }
- for (an in invisibleAnnotations ?: emptyList()) {
- if (anyAnnotations.contains(an.desc)) {
- return an
- }
- }
- return null
+ set: Set<String>,
+ visibleAnnotations: List<AnnotationNode>?,
+ invisibleAnnotations: List<AnnotationNode>?,
+): AnnotationNode? {
+ return visibleAnnotations?.find { it.desc in set }
+ ?: invisibleAnnotations?.find { it.desc in set }
}
fun ClassNode.findAnyAnnotation(set: Set<String>): AnnotationNode? {
@@ -70,6 +61,27 @@
return findAnyAnnotation(set, this.visibleAnnotations, this.invisibleAnnotations)
}
+fun findAllAnnotations(
+ set: Set<String>,
+ visibleAnnotations: List<AnnotationNode>?,
+ invisibleAnnotations: List<AnnotationNode>?
+): List<AnnotationNode> {
+ return (visibleAnnotations ?: emptyList()).filter { it.desc in set } +
+ (invisibleAnnotations ?: emptyList()).filter { it.desc in set }
+}
+
+fun ClassNode.findAllAnnotations(set: Set<String>): List<AnnotationNode> {
+ return findAllAnnotations(set, this.visibleAnnotations, this.invisibleAnnotations)
+}
+
+fun MethodNode.findAllAnnotations(set: Set<String>): List<AnnotationNode> {
+ return findAllAnnotations(set, this.visibleAnnotations, this.invisibleAnnotations)
+}
+
+fun FieldNode.findAllAnnotations(set: Set<String>): List<AnnotationNode> {
+ return findAllAnnotations(set, this.visibleAnnotations, this.invisibleAnnotations)
+}
+
fun <T> findAnnotationValueAsObject(
an: AnnotationNode,
propertyName: String,
@@ -327,6 +339,10 @@
return (this.access and Opcodes.ACC_PUBLIC) != 0
}
+fun MethodNode.isNative(): Boolean {
+ return (this.access and Opcodes.ACC_NATIVE) != 0
+}
+
fun MethodNode.isSpecial(): Boolean {
return CTOR_NAME == this.name || CLASS_INITIALIZER_NAME == this.name
}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/dumper/ApiDumper.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/dumper/ApiDumper.kt
index aaefee4..5e4e70f 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/dumper/ApiDumper.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/dumper/ApiDumper.kt
@@ -44,7 +44,7 @@
val descriptor: String,
)
- val javaStandardApiPolicy = FilterPolicy.Stub.withReason("Java standard API")
+ private val javaStandardApiPolicy = FilterPolicy.Keep.withReason("Java standard API")
private val shownMethods = mutableSetOf<MethodKey>()
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt
index 248121c..a6b8cdb 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AnnotationBasedFilter.kt
@@ -17,14 +17,16 @@
import com.android.hoststubgen.ClassParseException
import com.android.hoststubgen.HostStubGenErrors
-import com.android.hoststubgen.HostStubGenInternalException
import com.android.hoststubgen.InvalidAnnotationException
-import com.android.hoststubgen.addNonNullElement
+import com.android.hoststubgen.addLists
import com.android.hoststubgen.asm.CLASS_INITIALIZER_DESC
import com.android.hoststubgen.asm.CLASS_INITIALIZER_NAME
import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.findAllAnnotations
import com.android.hoststubgen.asm.findAnnotationValueAsString
import com.android.hoststubgen.asm.findAnyAnnotation
+import com.android.hoststubgen.asm.getPackageNameFromFullClassName
+import com.android.hoststubgen.asm.resolveClassNameWithDefaultPackage
import com.android.hoststubgen.asm.toHumanReadableClassName
import com.android.hoststubgen.asm.toHumanReadableMethodName
import com.android.hoststubgen.asm.toJvmClassName
@@ -35,395 +37,309 @@
// TODO: Detect invalid cases, such as...
// - Class's visibility is lower than the members'.
-// - HostSideTestSubstituteWith is set, but it doesn't have @Stub or @Keep
/**
* [OutputFilter] using Java annotations.
*/
class AnnotationBasedFilter(
- private val errors: HostStubGenErrors,
- private val classes: ClassNodes,
- stubAnnotations_: Set<String>,
- keepAnnotations_: Set<String>,
- stubClassAnnotations_: Set<String>,
- keepClassAnnotations_: Set<String>,
- throwAnnotations_: Set<String>,
- removeAnnotations_: Set<String>,
- substituteAnnotations_: Set<String>,
- nativeSubstituteAnnotations_: Set<String>,
- classLoadHookAnnotations_: Set<String>,
- keepStaticInitializerAnnotations_: Set<String>,
- private val annotationAllowedClassesFilter: ClassFilter,
- fallback: OutputFilter,
+ private val errors: HostStubGenErrors,
+ private val classes: ClassNodes,
+ keepAnnotations_: Set<String>,
+ keepClassAnnotations_: Set<String>,
+ throwAnnotations_: Set<String>,
+ removeAnnotations_: Set<String>,
+ substituteAnnotations_: Set<String>,
+ redirectAnnotations_: Set<String>,
+ redirectionClassAnnotations_: Set<String>,
+ classLoadHookAnnotations_: Set<String>,
+ keepStaticInitializerAnnotations_: Set<String>,
+ private val annotationAllowedClassesFilter: ClassFilter,
+ fallback: OutputFilter,
) : DelegatingFilter(fallback) {
- private var stubAnnotations = convertToInternalNames(stubAnnotations_)
- private var keepAnnotations = convertToInternalNames(keepAnnotations_)
- private var stubClassAnnotations = convertToInternalNames(stubClassAnnotations_)
- private var keepClassAnnotations = convertToInternalNames(keepClassAnnotations_)
- private var throwAnnotations = convertToInternalNames(throwAnnotations_)
- private var removeAnnotations = convertToInternalNames(removeAnnotations_)
- private var substituteAnnotations = convertToInternalNames(substituteAnnotations_)
- private var nativeSubstituteAnnotations = convertToInternalNames(nativeSubstituteAnnotations_)
- private var classLoadHookAnnotations = convertToInternalNames(classLoadHookAnnotations_)
- private var keepStaticInitializerAnnotations =
- convertToInternalNames(keepStaticInitializerAnnotations_)
+ private val keepAnnotations = convertToInternalNames(keepAnnotations_)
+ private val keepClassAnnotations = convertToInternalNames(keepClassAnnotations_)
+ private val throwAnnotations = convertToInternalNames(throwAnnotations_)
+ private val removeAnnotations = convertToInternalNames(removeAnnotations_)
+ private val redirectAnnotations = convertToInternalNames(redirectAnnotations_)
+ private val substituteAnnotations = convertToInternalNames(substituteAnnotations_)
+ private val redirectionClassAnnotations =
+ convertToInternalNames(redirectionClassAnnotations_)
+ private val classLoadHookAnnotations = convertToInternalNames(classLoadHookAnnotations_)
+ private val keepStaticInitializerAnnotations =
+ convertToInternalNames(keepStaticInitializerAnnotations_)
/** Annotations that control API visibility. */
- private var visibilityAnnotations: Set<String> = convertToInternalNames(
- stubAnnotations_ +
- keepAnnotations_ +
- stubClassAnnotations_ +
- keepClassAnnotations_ +
- throwAnnotations_ +
- removeAnnotations_)
+ private val visibilityAnnotations = keepAnnotations +
+ keepClassAnnotations +
+ throwAnnotations +
+ removeAnnotations +
+ redirectAnnotations +
+ substituteAnnotations
+
+ /** All the annotations we use. */
+ private val allAnnotations = visibilityAnnotations +
+ redirectionClassAnnotations +
+ classLoadHookAnnotations +
+ keepStaticInitializerAnnotations
/**
* All the annotations we use. Note, this one is in a [convertToJvmNames] format unlike
* other ones, because of how it's used.
*/
- private var allAnnotations: Set<String> = convertToJvmNames(
- stubAnnotations_ +
- keepAnnotations_ +
- stubClassAnnotations_ +
+ private val allAnnotationClasses: Set<String> = convertToJvmNames(
+ keepAnnotations_ +
keepClassAnnotations_ +
throwAnnotations_ +
removeAnnotations_ +
+ redirectAnnotations_ +
substituteAnnotations_ +
- nativeSubstituteAnnotations_ +
- classLoadHookAnnotations_)
+ redirectionClassAnnotations_ +
+ classLoadHookAnnotations_ +
+ keepStaticInitializerAnnotations_
+ )
- private val substitutionHelper = SubstitutionHelper()
+ private val policyCache = mutableMapOf<String, ClassAnnotations>()
- private val reasonAnnotation = "annotation"
- private val reasonClassAnnotation = "class-annotation"
-
- /**
- * Throw if an item has more than one visibility annotations.
- *
- * name1 - 4 are only used in exception messages. We take them as separate strings
- * to avoid unnecessary string concatenations.
- */
- private fun detectInvalidAnnotations(
- visibles: List<AnnotationNode>?,
- invisibles: List<AnnotationNode>?,
- type: String,
- name1: String,
- name2: String,
- name3: String,
- ) {
- var count = 0
- for (an in visibles ?: emptyList()) {
- if (visibilityAnnotations.contains(an.desc)) {
- count++
- }
- }
- for (an in invisibles ?: emptyList()) {
- if (visibilityAnnotations.contains(an.desc)) {
- count++
- }
- }
- if (count > 1) {
- val description = if (name2 == "" && name3 == "") {
- "$type $name1"
- } else {
- "$type $name1.$name2$name3"
- }
- throw InvalidAnnotationException(
- "Found more than one visibility annotations on $description")
+ private val AnnotationNode.policy: FilterPolicyWithReason? get() {
+ return when (desc) {
+ in keepAnnotations -> FilterPolicy.Keep.withReason(REASON_ANNOTATION)
+ in keepClassAnnotations -> FilterPolicy.KeepClass.withReason(REASON_CLASS_ANNOTATION)
+ in substituteAnnotations -> FilterPolicy.Substitute.withReason(REASON_ANNOTATION)
+ in throwAnnotations -> FilterPolicy.Throw.withReason(REASON_ANNOTATION)
+ in removeAnnotations -> FilterPolicy.Remove.withReason(REASON_ANNOTATION)
+ in redirectAnnotations -> FilterPolicy.Redirect.withReason(REASON_ANNOTATION)
+ else -> null
}
}
- fun findAnyAnnotation(
- className: String,
- anyAnnotations: Set<String>,
- visibleAnnotations: List<AnnotationNode>?,
- invisibleAnnotations: List<AnnotationNode>?,
- ): AnnotationNode? {
- val ret = findAnyAnnotation(anyAnnotations, visibleAnnotations, invisibleAnnotations)
+ private fun getAnnotationPolicy(cn: ClassNode): ClassAnnotations {
+ return policyCache.getOrPut(cn.name) { ClassAnnotations(cn) }
+ }
- if (ret != null) {
- if (!annotationAllowedClassesFilter.matches(className)) {
- throw InvalidAnnotationException(
- "Class ${className.toHumanReadableClassName()} is not allowed to have " +
- "Ravenwood annotations. Contact g/ravenwood for more details.")
+ override fun getPolicyForClass(className: String): FilterPolicyWithReason {
+ // If it's any of the annotations, then always keep it.
+ if (allAnnotationClasses.contains(className)) {
+ return FilterPolicy.KeepClass.withReason("HostStubGen Annotation")
+ }
+
+ val cn = classes.getClass(className)
+ return getAnnotationPolicy(cn).classPolicy ?: super.getPolicyForClass(className)
+ }
+
+ override fun getPolicyForField(className: String, fieldName: String): FilterPolicyWithReason {
+ val cn = classes.getClass(className)
+ return getAnnotationPolicy(cn).fieldPolicies[fieldName]
+ ?: super.getPolicyForField(className, fieldName)
+ }
+
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): FilterPolicyWithReason {
+ val cn = classes.getClass(className)
+ return getAnnotationPolicy(cn).methodPolicies[MethodKey(methodName, descriptor)]
+ ?: super.getPolicyForMethod(className, methodName, descriptor)
+ }
+
+ override fun getRenameTo(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): String? {
+ val cn = classes.getClass(className)
+ return getAnnotationPolicy(cn).renamedMethods[MethodKey(methodName, descriptor)]
+ ?: super.getRenameTo(className, methodName, descriptor)
+ }
+
+ override fun getRedirectionClass(className: String): String? {
+ val cn = classes.getClass(className)
+ return getAnnotationPolicy(cn).redirectionClass
+ }
+
+ override fun getClassLoadHooks(className: String): List<String> {
+ val cn = classes.getClass(className)
+ return addLists(super.getClassLoadHooks(className), getAnnotationPolicy(cn).classLoadHooks)
+ }
+
+ private data class MethodKey(val name: String, val desc: String)
+
+ /**
+ * Every time we see a class, we scan all its methods for substitution attributes,
+ * and compute (implicit) policies caused by them.
+ *
+ * For example, for the following methods:
+ *
+ * @Substitute(suffix = "_host")
+ * private void foo() {
+ * // This isn't supported on the host side.
+ * }
+ * private void foo_host() {
+ * // Host side implementation
+ * }
+ *
+ * We internally handle them as:
+ *
+ * foo() -> Substitute
+ * foo_host() -> Stub, and then rename it to foo().
+ */
+ private inner class ClassAnnotations(cn: ClassNode) {
+
+ val classPolicy: FilterPolicyWithReason?
+ val fieldPolicies = mutableMapOf<String, FilterPolicyWithReason>()
+ val methodPolicies = mutableMapOf<MethodKey, FilterPolicyWithReason>()
+ val renamedMethods = mutableMapOf<MethodKey, String>()
+ val redirectionClass: String?
+ val classLoadHooks: List<String>
+
+ init {
+ val allowAnnotation = annotationAllowedClassesFilter.matches(cn.name)
+ detectInvalidAnnotations(
+ cn.name, allowAnnotation,
+ cn.visibleAnnotations, cn.invisibleAnnotations,
+ "class", cn.name
+ )
+ classPolicy = cn.findAnyAnnotation(visibilityAnnotations)?.policy
+ redirectionClass = cn.findAnyAnnotation(redirectionClassAnnotations)?.let { an ->
+ getAnnotationField(an, "value")?.let { resolveRelativeClass(cn, it) }
+ }
+ classLoadHooks = cn.findAllAnnotations(classLoadHookAnnotations).mapNotNull { an ->
+ getAnnotationField(an, "value")?.toHumanReadableMethodName()
+ }
+ if (cn.findAnyAnnotation(keepStaticInitializerAnnotations) != null) {
+ methodPolicies[MethodKey(CLASS_INITIALIZER_NAME, CLASS_INITIALIZER_DESC)] =
+ FilterPolicy.Keep.withReason(REASON_ANNOTATION)
+ }
+
+ for (fn in cn.fields ?: emptyList()) {
+ detectInvalidAnnotations(
+ cn.name, allowAnnotation,
+ fn.visibleAnnotations, fn.invisibleAnnotations,
+ "field", cn.name, fn.name
+ )
+ fn.findAnyAnnotation(visibilityAnnotations)?.policy?.let {
+ fieldPolicies[fn.name] = it
+ }
+ }
+
+ for (mn in cn.methods ?: emptyList()) {
+ detectInvalidAnnotations(
+ cn.name, allowAnnotation,
+ mn.visibleAnnotations, mn.invisibleAnnotations,
+ "method", cn.name, mn.name, mn.desc
+ )
+
+ val an = mn.findAnyAnnotation(visibilityAnnotations) ?: continue
+ val policy = an.policy ?: continue
+ methodPolicies[MethodKey(mn.name, mn.desc)] = policy
+
+ if (policy.policy != FilterPolicy.Substitute) continue
+
+ // Handle substitution
+ val suffix = getAnnotationField(an, "suffix", false) ?: "\$ravenwood"
+ val replacement = mn.name + suffix
+
+ if (replacement == mn.name) {
+ errors.onErrorFound("@SubstituteWith require a different name")
+ } else {
+ // The replacement method has to be renamed
+ methodPolicies[MethodKey(replacement, mn.desc)] =
+ FilterPolicy.Keep.withReason(REASON_ANNOTATION)
+ renamedMethods[MethodKey(replacement, mn.desc)] = mn.name
+
+ log.v("Substitution found: %s%s -> %s", replacement, mn.desc, mn.name)
+ }
}
}
- return ret
- }
-
- /**
- * Find a visibility annotation.
- *
- * name1 - 4 are only used in exception messages.
- */
- private fun findAnnotation(
+ /**
+ * Throw if an item has more than one visibility annotations, or the class is not allowed
+ *
+ * name1 - 4 are only used in exception messages. We take them as separate strings
+ * to avoid unnecessary string concatenations.
+ */
+ private fun detectInvalidAnnotations(
className: String,
+ allowAnnotation: Boolean,
visibles: List<AnnotationNode>?,
invisibles: List<AnnotationNode>?,
type: String,
name1: String,
name2: String = "",
name3: String = "",
- ): FilterPolicyWithReason? {
- detectInvalidAnnotations(visibles, invisibles, type, name1, name2, name3)
-
- findAnyAnnotation(className, stubAnnotations, visibles, invisibles)?.let {
- return FilterPolicy.Stub.withReason(reasonAnnotation)
- }
- findAnyAnnotation(className, stubClassAnnotations, visibles, invisibles)?.let {
- return FilterPolicy.StubClass.withReason(reasonClassAnnotation)
- }
- findAnyAnnotation(className, keepAnnotations, visibles, invisibles)?.let {
- return FilterPolicy.Keep.withReason(reasonAnnotation)
- }
- findAnyAnnotation(className, keepClassAnnotations, visibles, invisibles)?.let {
- return FilterPolicy.KeepClass.withReason(reasonClassAnnotation)
- }
- findAnyAnnotation(className, throwAnnotations, visibles, invisibles)?.let {
- return FilterPolicy.Throw.withReason(reasonAnnotation)
- }
- findAnyAnnotation(className, removeAnnotations, visibles, invisibles)?.let {
- return FilterPolicy.Remove.withReason(reasonAnnotation)
- }
-
- return null
- }
-
- override fun getPolicyForClass(className: String): FilterPolicyWithReason {
- val cn = classes.getClass(className)
-
- findAnnotation(
- cn.name,
- cn.visibleAnnotations,
- cn.invisibleAnnotations,
- "class",
- className)?.let {
- return it
- }
-
- // If it's any of the annotations, then always keep it.
- if (allAnnotations.contains(className)) {
- return FilterPolicy.KeepClass.withReason("HostStubGen Annotation")
- }
-
- return super.getPolicyForClass(className)
- }
-
- override fun getPolicyForField(
- className: String,
- fieldName: String
- ): FilterPolicyWithReason {
- val cn = classes.getClass(className)
-
- cn.fields?.firstOrNull { it.name == fieldName }?.let {fn ->
- findAnnotation(
- cn.name,
- fn.visibleAnnotations,
- fn.invisibleAnnotations,
- "field",
- className,
- fieldName
- )?.let { policy ->
- // If the item has an annotation, then use it.
- return policy
+ ) {
+ var count = 0
+ var visibleCount = 0
+ for (an in visibles ?: emptyList()) {
+ if (visibilityAnnotations.contains(an.desc)) {
+ visibleCount++
+ }
+ if (allAnnotations.contains(an.desc)) {
+ count++
+ }
}
- }
- return super.getPolicyForField(className, fieldName)
- }
-
- override fun getPolicyForMethod(
- className: String,
- methodName: String,
- descriptor: String
- ): FilterPolicyWithReason {
- val cn = classes.getClass(className)
-
- if (methodName == CLASS_INITIALIZER_NAME && descriptor == CLASS_INITIALIZER_DESC) {
- findAnyAnnotation(cn.name, keepStaticInitializerAnnotations,
- cn.visibleAnnotations, cn.invisibleAnnotations)?.let {
- return FilterPolicy.Keep.withReason(reasonAnnotation)
+ for (an in invisibles ?: emptyList()) {
+ if (visibilityAnnotations.contains(an.desc)) {
+ visibleCount++
+ }
+ if (allAnnotations.contains(an.desc)) {
+ count++
+ }
}
- }
-
- cn.methods?.firstOrNull { it.name == methodName && it.desc == descriptor }?.let { mn ->
- // @SubstituteWith is going to complicate the policy here, so we ask helper
- // what to do.
- substitutionHelper.getPolicyFromSubstitution(cn, mn.name, mn.desc)?.let {
- return it
+ if (count > 0 && !allowAnnotation) {
+ throw InvalidAnnotationException(
+ "Class ${className.toHumanReadableClassName()} is not allowed to have " +
+ "Ravenwood annotations. Contact g/ravenwood for more details."
+ )
}
-
- // If there's no substitution, then we check the annotation.
- findAnnotation(
- cn.name,
- mn.visibleAnnotations,
- mn.invisibleAnnotations,
- "method",
- className,
- methodName,
- descriptor
- )?.let { policy ->
- return policy
+ if (visibleCount > 1) {
+ val description = if (name2 == "" && name3 == "") {
+ "$type $name1"
+ } else {
+ "$type $name1.$name2$name3"
+ }
+ throw InvalidAnnotationException(
+ "Found more than one visibility annotations on $description"
+ )
}
}
- return super.getPolicyForMethod(className, methodName, descriptor)
- }
-
- override fun getRenameTo(
- className: String,
- methodName: String,
- descriptor: String
- ): String? {
- val cn = classes.getClass(className)
-
- // If the method has a "substitute with" annotation, then return its "value" parameter.
- cn.methods?.firstOrNull { it.name == methodName && it.desc == descriptor }?.let { mn ->
- return substitutionHelper.getRenameTo(cn, mn.name, mn.desc)
- }
- return null
- }
-
- override fun getNativeSubstitutionClass(className: String): String? {
- classes.getClass(className).let { cn ->
- findAnyAnnotation(nativeSubstituteAnnotations,
- cn.visibleAnnotations, cn.invisibleAnnotations)?.let { an ->
- return getAnnotationField(an, "value")?.toJvmClassName()
- }
- }
- return null
- }
-
- override fun getClassLoadHooks(className: String): List<String> {
- val e = classes.getClass(className).let { cn ->
- findAnyAnnotation(classLoadHookAnnotations,
- cn.visibleAnnotations, cn.invisibleAnnotations)?.let { an ->
- getAnnotationField(an, "value")?.toHumanReadableMethodName()
- }
- }
- return addNonNullElement(super.getClassLoadHooks(className), e)
- }
-
- private data class MethodKey(val name: String, val desc: String)
-
- /**
- * In order to handle substitution, we need to build a reverse mapping of substitution
- * methods.
- *
- * This class automatically builds such a map internally that the above methods can
- * take advantage of.
- */
- private inner class SubstitutionHelper {
- private var currentClass: ClassNode? = null
-
- private var policiesFromSubstitution = mutableMapOf<MethodKey, FilterPolicyWithReason>()
- private var substituteToMethods = mutableMapOf<MethodKey, String>()
-
- fun getPolicyFromSubstitution(cn: ClassNode, methodName: String, descriptor: String):
- FilterPolicyWithReason? {
- setClass(cn)
- return policiesFromSubstitution[MethodKey(methodName, descriptor)]
- }
-
- fun getRenameTo(cn: ClassNode, methodName: String, descriptor: String): String? {
- setClass(cn)
- return substituteToMethods[MethodKey(methodName, descriptor)]
- }
/**
- * Every time we see a different class, we scan all its methods for substitution attributes,
- * and compute (implicit) policies caused by them.
- *
- * For example, for the following methods:
- *
- * @Stub
- * @Substitute(suffix = "_host")
- * private void foo() {
- * // This isn't supported on the host side.
- * }
- * private void foo_host() {
- * // Host side implementation
- * }
- *
- * We internally handle them as:
- *
- * foo() -> Remove
- * foo_host() -> Stub, and then rename it to foo().
+ * Return the (String) value of 'value' parameter from an annotation.
*/
- private fun setClass(cn: ClassNode) {
- if (currentClass == cn) {
- return
- }
- // If the class is changing, we'll rebuild the internal structure.
- currentClass = cn
-
- policiesFromSubstitution.clear()
- substituteToMethods.clear()
-
- for (mn in cn.methods ?: emptyList()) {
- findAnyAnnotation(substituteAnnotations,
- mn.visibleAnnotations,
- mn.invisibleAnnotations)?.let { an ->
-
- // Find the policy for this method.
- val policy = outermostFilter.getPolicyForMethod(cn.name, mn.name, mn.desc)
- .policy.resolveClassWidePolicy()
- // Make sure it's either Stub or Keep.
- if (!(policy.needsInStub || policy.needsInImpl)) {
- // TODO: Use the real annotation names in the message
- errors.onErrorFound("@SubstituteWith must have either @Stub or @Keep")
- return@let
- }
- if (!policy.isUsableWithMethods) {
- throw HostStubGenInternalException("Policy $policy shouldn't show up here")
- }
-
- val suffix = getAnnotationField(an, "suffix", false) ?: "\$ravenwood"
- val renameFrom = mn.name + suffix
- val renameTo = mn.name
-
- if (renameFrom == renameTo) {
- errors.onErrorFound("@SubstituteWith have a different name")
- return@let
- }
-
- // This mn has "SubstituteWith". This means,
- // 1. Re move the "rename-to" method, so add it to substitutedMethods.
- policiesFromSubstitution[MethodKey(renameTo, mn.desc)] =
- FilterPolicy.Remove.withReason("substitute-to")
-
- // If the policy is "stub", use "stub".
- // Otherwise, it must be "keep" or "throw", but there's no point in using
- // "throw", so let's use "keep".
- val newPolicy = if (policy.needsInStub) policy else FilterPolicy.Keep
- // 2. We also keep the from-to in the map.
- policiesFromSubstitution[MethodKey(renameFrom, mn.desc)] =
- newPolicy.withReason("substitute-from")
- substituteToMethods[MethodKey(renameFrom, mn.desc)] = renameTo
-
- log.v("Substitution found: %s%s -> %s", renameFrom, mn.desc, renameTo)
+ private fun getAnnotationField(
+ an: AnnotationNode,
+ name: String,
+ required: Boolean = true
+ ): String? {
+ try {
+ val suffix = findAnnotationValueAsString(an, name)
+ if (suffix == null && required) {
+ errors.onErrorFound("Annotation \"${an.desc}\" must have field $name")
}
+ return suffix
+ } catch (e: ClassParseException) {
+ errors.onErrorFound(e.message!!)
+ return null
}
}
- }
- /**
- * Return the (String) value of 'value' parameter from an annotation.
- */
- private fun getAnnotationField(an: AnnotationNode, name: String,
- required: Boolean = true): String? {
- try {
- val suffix = findAnnotationValueAsString(an, name)
- if (suffix == null && required) {
- errors.onErrorFound("Annotation \"${an.desc}\" must have field $name")
- }
- return suffix
- } catch (e: ClassParseException) {
- errors.onErrorFound(e.message!!)
- return null
+ /**
+ * Resolve the full class name if the class is relative
+ */
+ private fun resolveRelativeClass(
+ cn: ClassNode,
+ name: String
+ ): String {
+ val packageName = getPackageNameFromFullClassName(cn.name)
+ return resolveClassNameWithDefaultPackage(name, packageName).toJvmClassName()
}
}
companion object {
+ private const val REASON_ANNOTATION = "annotation"
+ private const val REASON_CLASS_ANNOTATION = "class-annotation"
+
/**
* Convert from human-readable type names (e.g. "com.android.TypeName") to the internal type
* names (e.g. "Lcom/android/TypeName).
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt
index 37048d9..f8bb526 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ClassWidePolicyPropagatingFilter.kt
@@ -52,7 +52,7 @@
private fun getClassWidePolicy(className: String, resolve: Boolean): FilterPolicyWithReason? {
outermostFilter.getPolicyForClass(className).let { policy ->
- if (policy.policy.isClassWidePolicy) {
+ if (policy.policy == FilterPolicy.KeepClass) {
val p = if (resolve) {
policy.policy.resolveClassWidePolicy()
} else {
@@ -88,6 +88,6 @@
descriptor: String
): FilterPolicyWithReason {
return getClassWidePolicy(className, resolve = true)
- ?: super.getPolicyForMethod(className, methodName, descriptor)
+ ?: super.getPolicyForMethod(className, methodName, descriptor)
}
-}
\ No newline at end of file
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt
index 678e6ea..be3c59c 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ConstantFilter.kt
@@ -26,23 +26,17 @@
* @param policy the policy. Cannot be a "substitute" policy.
*/
class ConstantFilter(
- policy: FilterPolicy,
- val reason: String
+ policy: FilterPolicy,
+ private val reason: String
) : OutputFilter() {
- val classPolicy: FilterPolicy
- val fieldPolicy: FilterPolicy
- val methodPolicy: FilterPolicy
+
+ private val classPolicy: FilterPolicy
+ private val fieldPolicy: FilterPolicy
+ private val methodPolicy: FilterPolicy
init {
- if (policy.isSubstitute) {
- throw HostStubGenInternalException(
- "ConstantFilter doesn't allow substitution policies.")
- }
- if (policy.isClassWidePolicy) {
- // We prevent it, because there's no point in using class-wide policies because
- // all members get othe same policy too anyway.
- throw HostStubGenInternalException(
- "ConstantFilter doesn't allow class-wide policies.")
+ if (!policy.isUsableWithDefault) {
+ throw HostStubGenInternalException("ConstantFilter doesn't support $policy.")
}
methodPolicy = policy
@@ -63,10 +57,10 @@
}
override fun getPolicyForMethod(
- className: String,
- methodName: String,
- descriptor: String,
- ): FilterPolicyWithReason {
+ className: String,
+ methodName: String,
+ descriptor: String,
+ ): FilterPolicyWithReason {
return methodPolicy.withReason(reason)
}
}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt
index 6fcffb8..b8b0d8a 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/DelegatingFilter.kt
@@ -72,8 +72,8 @@
return fallback.getRenameTo(className, methodName, descriptor)
}
- override fun getNativeSubstitutionClass(className: String): String? {
- return fallback.getNativeSubstitutionClass(className)
+ override fun getRedirectionClass(className: String): String? {
+ return fallback.getRedirectionClass(className)
}
override fun getClassLoadHooks(className: String): List<String> {
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt
index f839444..2f2f81b 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicy.kt
@@ -17,37 +17,25 @@
enum class FilterPolicy {
/**
- * Keep the item in the stub jar file, so tests can use it.
- */
- Stub,
-
- /**
- * Keep the item in the impl jar file, but not in the stub file. Tests cannot use it directly,
- * but indirectly.
+ * Keep the item in the jar file.
*/
Keep,
/**
- * Only used for types. Keep the class in the stub, and also all its members.
- * But each member can have another annotations to override it.
- */
- StubClass,
-
- /**
- * Only used for types. Keep the class in the impl, not in the stub, and also all its members.
- * But each member can have another annotations to override it.
+ * Only usable with classes. Keep the class in the jar, and also all its members.
+ * Each member can have another policy to override it.
*/
KeepClass,
/**
- * Same as [Stub], but replace it with a "substitution" method. Only usable with methods.
+ * Only usable with methods. Replace a method with a "substitution" method.
*/
- SubstituteAndStub,
+ Substitute,
/**
- * Same as [Keep], but replace it with a "substitution" method. Only usable with methods.
+ * Only usable with methods. Redirect a method to a method in the substitution class.
*/
- SubstituteAndKeep,
+ Redirect,
/**
* Only usable with methods. The item will be kept in the impl jar file, but when called,
@@ -57,7 +45,7 @@
/**
* Only usable with methods. The item will be kept in the impl jar file, but when called,
- * it'll no-op. Currently only supported for methods returning `void`.
+ * it'll no-op.
*/
Ignore,
@@ -66,20 +54,19 @@
*/
Remove;
- val isSubstitute: Boolean
- get() = this == SubstituteAndStub || this == SubstituteAndKeep
-
- val needsInStub: Boolean
- get() = this == Stub || this == StubClass || this == SubstituteAndStub || this == Ignore
-
- val needsInImpl: Boolean
- get() = this != Remove
+ val needsInOutput: Boolean
+ get() {
+ return when (this) {
+ Remove -> false
+ else -> true
+ }
+ }
/** Returns whether a policy can be used with classes */
val isUsableWithClasses: Boolean
get() {
return when (this) {
- Stub, StubClass, Keep, KeepClass, Remove -> true
+ Keep, KeepClass, Remove -> true
else -> false
}
}
@@ -88,7 +75,7 @@
val isUsableWithFields: Boolean
get() {
return when (this) {
- Stub, Keep, Remove -> true
+ Keep, Remove -> true
else -> false
}
}
@@ -97,16 +84,16 @@
val isUsableWithMethods: Boolean
get() {
return when (this) {
- StubClass, KeepClass -> false
+ KeepClass -> false
else -> true
}
}
- /** Returns whether a policy is a class-wide one. */
- val isClassWidePolicy: Boolean
+ /** Returns whether a policy can be used as default policy. */
+ val isUsableWithDefault: Boolean
get() {
return when (this) {
- StubClass, KeepClass -> true
+ Keep, Throw, Remove -> true
else -> false
}
}
@@ -115,26 +102,24 @@
val isSupported: Boolean
get() {
return when (this) {
- // TODO: handle native method with no substitution as being unsupported
- Stub, StubClass, Keep, KeepClass, SubstituteAndStub, SubstituteAndKeep -> true
+ Keep, KeepClass, Substitute, Redirect -> true
else -> false
}
}
- fun getSubstitutionBasePolicy(): FilterPolicy {
- return when (this) {
- SubstituteAndKeep -> Keep
- SubstituteAndStub -> Stub
- else -> this
+ val isMethodRewriteBody: Boolean
+ get() {
+ return when (this) {
+ Redirect, Throw, Ignore -> true
+ else -> false
+ }
}
- }
/**
- * Convert {Stub,Keep}Class to the corresponding Stub or Keep.
+ * Convert KeepClass to Keep, or return itself.
*/
fun resolveClassWidePolicy(): FilterPolicy {
return when (this) {
- StubClass -> Stub
KeepClass -> Keep
else -> this
}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt
index eb03f66..b10165b 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/FilterPolicyWithReason.kt
@@ -30,36 +30,6 @@
return FilterPolicyWithReason(policy, "$reason [inner-reason: ${this.reason}]")
}
- /**
- * If the visibility is lower than "Keep" (meaning if it's "remove"),
- * then return a new [FilterPolicy] with "Keep".
- * Otherwise, return itself
- */
- fun promoteToKeep(promotionReason: String): FilterPolicyWithReason {
- if (policy.needsInImpl) {
- return this
- }
- val newPolicy = if (policy.isClassWidePolicy) FilterPolicy.KeepClass else FilterPolicy.Keep
-
- return FilterPolicyWithReason(newPolicy,
- "$promotionReason [original remove reason: ${this.reason}]")
- }
-
- /**
- * If the visibility is above "Keep" (meaning if it's "stub"),
- * then return a new [FilterPolicy] with "Keep".
- * Otherwise, return itself
- */
- fun demoteToKeep(promotionReason: String): FilterPolicyWithReason {
- if (!policy.needsInStub) {
- return this
- }
- val newPolicy = if (policy.isClassWidePolicy) FilterPolicy.KeepClass else FilterPolicy.Keep
-
- return FilterPolicyWithReason(newPolicy,
- "$promotionReason [original stub reason: ${this.reason}]")
- }
-
override fun toString(): String {
return "[$policy - reason: $reason]"
}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt
index 5a26fc6..474da6d 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/ImplicitOutputFilter.kt
@@ -25,7 +25,6 @@
import com.android.hoststubgen.asm.isAutoGeneratedEnumMember
import com.android.hoststubgen.asm.isEnum
import com.android.hoststubgen.asm.isSynthetic
-import com.android.hoststubgen.asm.isVisibilityPrivateOrPackagePrivate
import com.android.hoststubgen.log
import org.objectweb.asm.tree.ClassNode
@@ -53,7 +52,7 @@
}
// If the outer class needs to be in impl, it should be in impl too.
val outerPolicy = outermostFilter.getPolicyForClass(cn.outerClass)
- if (outerPolicy.policy.needsInImpl) {
+ if (outerPolicy.policy.needsInOutput) {
return FilterPolicy.KeepClass.withReason("anonymous-inner-class")
}
}
@@ -79,19 +78,6 @@
val fallback = super.getPolicyForMethod(className, methodName, descriptor)
val classPolicy = outermostFilter.getPolicyForClass(className)
- // If the class is in the stub, then we need to put the private constructor in the stub too,
- // to prevent the class from getting instantiated.
- if (classPolicy.policy.needsInStub &&
- !fallback.policy.needsInStub &&
- (methodName == "<init>") && // Constructor?
- (descriptor == "()V")) { // Has zero parameters?
- classes.findMethod(className, methodName, descriptor)?.let { mn ->
- if (isVisibilityPrivateOrPackagePrivate(mn.access)) {
- return FilterPolicy.Stub.withReason("private constructor in stub class")
- }
- }
- }
-
val cn = classes.getClass(className)
// If we throw from the static initializer, the class would be useless, so we convert it
@@ -107,7 +93,7 @@
}
log.d("Class ${cn.name} Class policy: $classPolicy")
- if (classPolicy.policy.needsInImpl) {
+ if (classPolicy.policy.needsInOutput) {
// Do it only when the class needs to be kept...
// Member policy should be "keep" or "stub".
@@ -152,7 +138,7 @@
val classPolicy = outermostFilter.getPolicyForClass(className)
log.d("Class ${cn.name} Class policy: $classPolicy")
- if (classPolicy.policy.needsInImpl) {
+ if (classPolicy.policy.needsInOutput) {
// Do it only when the class needs to be kept...
// Member policy should be "keep" or "stub".
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt
index 2e144f5..59fa464 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/InMemoryOutputFilter.kt
@@ -19,6 +19,7 @@
import com.android.hoststubgen.asm.ClassNodes
import com.android.hoststubgen.asm.toHumanReadableClassName
import com.android.hoststubgen.asm.toHumanReadableMethodName
+import com.android.hoststubgen.asm.toJvmClassName
import com.android.hoststubgen.log
// TODO: Validate all input names.
@@ -29,7 +30,7 @@
) : DelegatingFilter(fallback) {
private val mPolicies: MutableMap<String, FilterPolicyWithReason> = mutableMapOf()
private val mRenames: MutableMap<String, String> = mutableMapOf()
- private val mNativeSubstitutionClasses: MutableMap<String, String> = mutableMapOf()
+ private val mRedirectionClasses: MutableMap<String, String> = mutableMapOf()
private val mClassLoadHooks: MutableMap<String, String> = mutableMapOf()
private fun getClassKey(className: String): String {
@@ -115,17 +116,17 @@
mRenames[getMethodKey(className, methodName, descriptor)] = toName
}
- override fun getNativeSubstitutionClass(className: String): String? {
- return mNativeSubstitutionClasses[getClassKey(className)]
- ?: super.getNativeSubstitutionClass(className)
+ override fun getRedirectionClass(className: String): String? {
+ return mRedirectionClasses[getClassKey(className)]
+ ?: super.getRedirectionClass(className)
}
- fun setNativeSubstitutionClass(from: String, to: String) {
+ fun setRedirectionClass(from: String, to: String) {
checkClass(from)
- // Native substitute classes may be provided from other jars, so we can't do this check.
+ // Redirection classes may be provided from other jars, so we can't do this check.
// ensureClassExists(to)
- mNativeSubstitutionClasses[getClassKey(from)] = to.toHumanReadableClassName()
+ mRedirectionClasses[getClassKey(from)] = to.toJvmClassName()
}
override fun getClassLoadHooks(className: String): List<String> {
@@ -136,4 +137,4 @@
fun setClassLoadHook(className: String, methodName: String) {
mClassLoadHooks[getClassKey(className)] = methodName.toHumanReadableMethodName()
}
-}
\ No newline at end of file
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepNativeFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepNativeFilter.kt
new file mode 100644
index 0000000..00e7d77
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/KeepNativeFilter.kt
@@ -0,0 +1,43 @@
+/*
+ * 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.hoststubgen.filters
+
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.isNative
+
+/**
+ * For native methods that weren't handled by outer filters, we keep it so that
+ * native method registration will not crash at runtime. Ideally we shouldn't need
+ * this, but in practice unsupported native method registrations do occur.
+ */
+class KeepNativeFilter(
+ private val classes: ClassNodes,
+ fallback: OutputFilter
+) : DelegatingFilter(fallback) {
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String,
+ ): FilterPolicyWithReason {
+ return classes.findMethod(className, methodName, descriptor)?.let { mn ->
+ if (mn.isNative()) {
+ FilterPolicy.Keep.withReason("native-preserve")
+ } else {
+ null
+ }
+ } ?: super.getPolicyForMethod(className, methodName, descriptor)
+ }
+}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt
index 1049e2b..f99ce90 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/OutputFilter.kt
@@ -35,10 +35,6 @@
* using it.
*/
open var outermostFilter: OutputFilter = this
- get() = field
- set(value) {
- field = value
- }
abstract fun getPolicyForClass(className: String): FilterPolicyWithReason
@@ -60,13 +56,13 @@
}
/**
- * Return a "native substitution class" name for a given class.
+ * Return a "redirection class" name for a given class.
*
- * The result will be in a "human readable" form. (e.g. uses '.'s instead of '/'s)
+ * The result will be in a JVM internal form. (e.g. uses '/'s instead of '.'s)
*
- * (which corresponds to @HostSideTestNativeSubstitutionClass of the standard annotations.)
+ * (which corresponds to @HostSideTestRedirectClass of the standard annotations.)
*/
- open fun getNativeSubstitutionClass(className: String): String? {
+ open fun getRedirectionClass(className: String): String? {
return null
}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/SanitizationFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/SanitizationFilter.kt
new file mode 100644
index 0000000..18a1e16
--- /dev/null
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/SanitizationFilter.kt
@@ -0,0 +1,57 @@
+/*
+ * 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.hoststubgen.filters
+
+import com.android.hoststubgen.HostStubGenErrors
+import com.android.hoststubgen.asm.ClassNodes
+import com.android.hoststubgen.asm.toHumanReadableClassName
+import com.android.hoststubgen.log
+
+/**
+ * Check whether the policies in the inner layers make sense, and sanitize the results.
+ */
+class SanitizationFilter(
+ private val errors: HostStubGenErrors,
+ private val classes: ClassNodes,
+ fallback: OutputFilter
+) : DelegatingFilter(fallback) {
+ override fun getPolicyForMethod(
+ className: String,
+ methodName: String,
+ descriptor: String
+ ): FilterPolicyWithReason {
+ val policy = super.getPolicyForMethod(className, methodName, descriptor)
+ if (policy.policy == FilterPolicy.Redirect) {
+ // Check whether the hosting class has a redirection class
+ if (getRedirectionClass(className) == null) {
+ errors.onErrorFound("Method $methodName$descriptor requires a redirection " +
+ "class set on ${className.toHumanReadableClassName()}")
+ }
+ }
+ return policy
+ }
+
+ override fun getRedirectionClass(className: String): String? {
+ return super.getRedirectionClass(className)?.also { clazz ->
+ if (classes.findClass(clazz) == null) {
+ log.w("Redirection class $clazz not found. Class must be available at runtime.")
+ } else if (outermostFilter.getPolicyForClass(clazz).policy != FilterPolicy.KeepClass) {
+ // If the class exists, it must have a KeepClass policy.
+ errors.onErrorFound("Redirection class $clazz must have @KeepWholeClass.")
+ }
+ }
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt
deleted file mode 100644
index f92a027..0000000
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/StubIntersectingFilter.kt
+++ /dev/null
@@ -1,91 +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.hoststubgen.filters
-
-import com.android.hoststubgen.HostStubGenErrors
-import com.android.hoststubgen.asm.ClassNodes
-
-private const val REASON = "demoted, not in intersect jars"
-
-/**
- * An [OutputFilter] that will restrict what to put in stub to only what shows up in "intersecting
- * jar" files.
- *
- * For example, if the Android public API stub jar is provided, then the HostStubGen's output
- * stub will be restricted to public APIs.
- */
-class StubIntersectingFilter(
- private val errors: HostStubGenErrors,
- /**
- * If a class / field / method is not in any of these jars, then we will not put it in
- * stub.
- */
- private val intersectingJars: Map<String, ClassNodes>,
- fallback: OutputFilter,
-) : DelegatingFilter(fallback) {
- private inline fun exists(predicate: (ClassNodes) -> Boolean): Boolean {
- intersectingJars.forEach { entry ->
- if (predicate(entry.value)) {
- return true
- }
- }
- return false
- }
-
- /**
- * If [origPolicy] is less than "Stub", then return it as-is.
- *
- * Otherwise, call [inStubChecker] to see if the API is in any of [intersectingJars].
- * If yes, then return [origPolicy] as-is. Otherwise, demote to "Keep".
- */
- private fun intersectWithStub(
- origPolicy: FilterPolicyWithReason,
- inStubChecker: () -> Boolean,
- ): FilterPolicyWithReason {
- if (origPolicy.policy.needsInStub) {
- // Only check the stub jars, when the class is supposed to be in stub otherwise.
- if (!inStubChecker()) {
- return origPolicy.demoteToKeep(REASON)
- }
- }
- return origPolicy
- }
-
- override fun getPolicyForClass(className: String): FilterPolicyWithReason {
- return intersectWithStub(super.getPolicyForClass(className)) {
- exists { classes -> classes.findClass(className) != null }
- }
- }
-
- override fun getPolicyForField(
- className: String,
- fieldName: String
- ): FilterPolicyWithReason {
- return intersectWithStub(super.getPolicyForField(className, fieldName)) {
- exists { classes -> classes.findField(className, fieldName) != null }
- }
- }
-
- override fun getPolicyForMethod(
- className: String,
- methodName: String,
- descriptor: String
- ): FilterPolicyWithReason {
- return intersectWithStub(super.getPolicyForMethod(className, methodName, descriptor)) {
- exists { classes -> classes.findMethod(className, methodName, descriptor) != null }
- }
- }
-}
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
index 53bcf10..073b503 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/TextFileFilterPolicyParser.kt
@@ -142,9 +142,9 @@
throw ParseException(
"Special class can't have a substitution")
}
- // It's a native-substitution.
+ // It's a redirection class.
val toClass = fields[2].substring(1)
- imf.setNativeSubstitutionClass(className, toClass)
+ imf.setRedirectionClass(className, toClass)
} else if (fields[2].startsWith("~")) {
if (classType != SpecialClass.NotSpecial) {
// We could support it, but not needed at least for now.
@@ -240,7 +240,7 @@
imf.setPolicyForMethod(className, name, signature,
policy.withReason(FILTER_REASON))
- if (policy.isSubstitute) {
+ if (policy == FilterPolicy.Substitute) {
val fromName = fields[3].substring(1)
if (fromName == name) {
@@ -248,10 +248,9 @@
"Substitution must have a different name")
}
- // Set the policy for the "from" method.
+ // Set the policy for the "from" method.
imf.setPolicyForMethod(className, fromName, signature,
- policy.getSubstitutionBasePolicy()
- .withReason(FILTER_REASON))
+ FilterPolicy.Keep.withReason(FILTER_REASON))
val classAndMethod = splitWithLastPeriod(fromName)
if (classAndMethod != null) {
@@ -346,18 +345,15 @@
private fun parsePolicy(s: String): FilterPolicy {
return when (s.lowercase()) {
- "s", "stub" -> FilterPolicy.Stub
"k", "keep" -> FilterPolicy.Keep
"t", "throw" -> FilterPolicy.Throw
"r", "remove" -> FilterPolicy.Remove
- "sc", "stubclass" -> FilterPolicy.StubClass
"kc", "keepclass" -> FilterPolicy.KeepClass
"i", "ignore" -> FilterPolicy.Ignore
+ "rdr", "redirect" -> FilterPolicy.Redirect
else -> {
if (s.startsWith("@")) {
- FilterPolicy.SubstituteAndStub
- } else if (s.startsWith("%")) {
- FilterPolicy.SubstituteAndKeep
+ FilterPolicy.Substitute
} else {
throw ParseException("Invalid policy \"$s\"")
}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/utils/ClassFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/utils/ClassFilter.kt
index 01a7ab3..7440b94 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/utils/ClassFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/utils/ClassFilter.kt
@@ -24,19 +24,19 @@
/**
* General purpose filter for class names.
*/
-class ClassFilter private constructor (
- val defaultResult: Boolean,
+class ClassFilter private constructor(
+ private val defaultResult: Boolean,
) {
- private data class FilterElement(
- val allowed: Boolean,
- val internalName: String,
- val isPrefix: Boolean,
+ private class FilterElement(
+ val allowed: Boolean,
+ val internalName: String,
+ val isPrefix: Boolean,
) {
fun matches(classInternalName: String): Boolean {
- if (isPrefix) {
- return classInternalName.startsWith(internalName)
+ return if (isPrefix) {
+ classInternalName.startsWith(internalName)
} else {
- return classInternalName == internalName
+ classInternalName == internalName
}
}
}
@@ -54,15 +54,16 @@
return it
}
- var result = defaultResult
- run outer@{
- elements.forEach { e ->
- if (e.matches(classInternalName)) {
- result = e.allowed
- return@outer // break equivalent.
- }
+ val testClasses = sequence {
+ // Yield itself and its outer class(es) one by one
+ var idx = classInternalName.length
+ while (idx > 0) {
+ yield(classInternalName.substring(0, idx))
+ idx = classInternalName.lastIndexOf('$', idx - 1)
}
}
+
+ val result = elements.find { testClasses.any(it::matches) }?.allowed ?: defaultResult
cache[classInternalName] = result
return result
@@ -87,9 +88,9 @@
/** Build a filter from a string (for unit tests). */
fun buildFromString(
- filterString: String,
- defaultResult: Boolean,
- filenameForErrorMessage: String
+ filterString: String,
+ defaultResult: Boolean,
+ filenameForErrorMessage: String
): ClassFilter {
val ret = ClassFilter(defaultResult)
@@ -119,17 +120,20 @@
// Handle wildcard -- e.g. "package.name.*"
if (line.endsWith(".*")) {
- ret.elements.add(FilterElement(
- allow, line.substring(0, line.length - 2).toJvmClassName(), true))
+ ret.elements.add(
+ FilterElement(
+ allow, line.substring(0, line.length - 2).toJvmClassName(), true
+ )
+ )
return@forEach
}
// Any other uses of "*" would be an error.
if (line.contains('*')) {
throw ParseException(
- "Wildcard (*) can only show up as the last element",
- filenameForErrorMessage,
- lineNo
+ "Wildcard (*) can only show up as the last element",
+ filenameForErrorMessage,
+ lineNo
)
}
ret.elements.add(FilterElement(allow, line.toJvmClassName(), false))
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
index bad0449..261ef59c 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
@@ -21,103 +21,64 @@
import com.android.hoststubgen.asm.ClassNodes
import com.android.hoststubgen.asm.UnifiedVisitor
import com.android.hoststubgen.asm.getPackageNameFromFullClassName
-import com.android.hoststubgen.asm.resolveClassNameWithDefaultPackage
-import com.android.hoststubgen.asm.toJvmClassName
import com.android.hoststubgen.filters.FilterPolicy
import com.android.hoststubgen.filters.FilterPolicyWithReason
import com.android.hoststubgen.filters.OutputFilter
-import com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-import com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+import com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
import com.android.hoststubgen.log
+import java.io.PrintWriter
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.FieldVisitor
import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes
import org.objectweb.asm.commons.ClassRemapper
-import org.objectweb.asm.commons.Remapper
import org.objectweb.asm.util.TraceClassVisitor
-import java.io.PrintWriter
-val OPCODE_VERSION = Opcodes.ASM9
+const val OPCODE_VERSION = Opcodes.ASM9
-abstract class BaseAdapter (
- protected val classes: ClassNodes,
- nextVisitor: ClassVisitor,
- protected val filter: OutputFilter,
- protected val options: Options,
+abstract class BaseAdapter(
+ protected val classes: ClassNodes,
+ nextVisitor: ClassVisitor,
+ protected val filter: OutputFilter,
+ protected val options: Options,
) : ClassVisitor(OPCODE_VERSION, nextVisitor) {
/**
* Options to control the behavior.
*/
- data class Options (
- val errors: HostStubGenErrors,
- val stats: HostStubGenStats?,
- val enablePreTrace: Boolean,
- val enablePostTrace: Boolean,
- val enableNonStubMethodCallDetection: Boolean,
- )
+ data class Options(
+ val errors: HostStubGenErrors,
+ val stats: HostStubGenStats?,
+ val enablePreTrace: Boolean,
+ val enablePostTrace: Boolean
+ )
protected lateinit var currentPackageName: String
protected lateinit var currentClassName: String
- protected var nativeSubstitutionClass: String? = null
+ protected var redirectionClass: String? = null
protected lateinit var classPolicy: FilterPolicyWithReason
- /**
- * Return whether an item with a given policy should be included in the output.
- */
- protected abstract fun shouldEmit(policy: FilterPolicy): Boolean
-
- /**
- * Inject [HostStubGenKeptInStub] and [HostStubGenKeptInImpl] as needed to an item.
- */
- protected fun injectInStubAndKeepAnnotations(policy: FilterPolicy, v: UnifiedVisitor) {
- if (policy.needsInStub) {
- v.visitAnnotation(HostStubGenKeptInStub.CLASS_DESCRIPTOR, true)
- }
- if (policy.needsInImpl) {
- v.visitAnnotation(HostStubGenKeptInImpl.CLASS_DESCRIPTOR, true)
- }
- }
-
override fun visit(
- version: Int,
- access: Int,
- name: String,
- signature: String?,
- superName: String?,
- interfaces: Array<String>,
+ version: Int,
+ access: Int,
+ name: String,
+ signature: String?,
+ superName: String?,
+ interfaces: Array<String>,
) {
super.visit(version, access, name, signature, superName, interfaces)
currentClassName = name
currentPackageName = getPackageNameFromFullClassName(name)
classPolicy = filter.getPolicyForClass(currentClassName)
+ redirectionClass = filter.getRedirectionClass(currentClassName)
log.d("[%s] visit: %s (package: %s)", this.javaClass.simpleName, name, currentPackageName)
log.indent()
log.v("Emitting class: %s", name)
log.indent()
- filter.getNativeSubstitutionClass(currentClassName)?.let { className ->
- val fullClassName = resolveClassNameWithDefaultPackage(className, currentPackageName)
- .toJvmClassName()
- log.d(" NativeSubstitutionClass: $fullClassName")
- if (classes.findClass(fullClassName) == null) {
- log.w("Native substitution class $fullClassName not found. Class must be " +
- "available at runtime.")
- } else {
- // If the class exists, it must have a KeepClass policy.
- if (filter.getPolicyForClass(fullClassName).policy != FilterPolicy.KeepClass) {
- // TODO: Use real annotation name.
- options.errors.onErrorFound(
- "Native substitution class $fullClassName should have @Keep.")
- }
- }
-
- nativeSubstitutionClass = fullClassName
- }
// Inject annotations to generated classes.
- injectInStubAndKeepAnnotations(classPolicy.policy, UnifiedVisitor.on(this))
+ UnifiedVisitor.on(this).visitAnnotation(HostStubGenProcessedAsKeep.CLASS_DESCRIPTOR, true)
}
override fun visitEnd() {
@@ -141,11 +102,11 @@
}
override fun visitField(
- access: Int,
- name: String,
- descriptor: String,
- signature: String?,
- value: Any?,
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ value: Any?,
): FieldVisitor? {
if (skipMemberModificationNestCount > 0) {
return super.visitField(access, name, descriptor, signature, value)
@@ -154,7 +115,7 @@
log.d("visitField: %s %s [%x] Policy: %s", name, descriptor, access, policy)
log.withIndent {
- if (!shouldEmit(policy.policy)) {
+ if (policy.policy == FilterPolicy.Remove) {
log.d("Removing %s %s", name, policy)
return null
}
@@ -162,18 +123,19 @@
log.v("Emitting field: %s %s %s", name, descriptor, policy)
val ret = super.visitField(access, name, descriptor, signature, value)
- injectInStubAndKeepAnnotations(policy.policy, UnifiedVisitor.on(ret))
+ UnifiedVisitor.on(ret)
+ .visitAnnotation(HostStubGenProcessedAsKeep.CLASS_DESCRIPTOR, true)
return ret
}
}
override fun visitMethod(
- access: Int,
- name: String,
- descriptor: String,
- signature: String?,
- exceptions: Array<String>?,
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
): MethodVisitor? {
if (skipMemberModificationNestCount > 0) {
return super.visitMethod(access, name, descriptor, signature, exceptions)
@@ -187,11 +149,11 @@
// Instead of this method, we rename the substitute-to method with the original
// name, in the "Maybe rename the method" part below.
val policy = filter.getPolicyForMethod(currentClassName, name, descriptor)
- if (policy.policy.isSubstitute) {
+ if (policy.policy == FilterPolicy.Substitute) {
log.d("Skipping %s%s %s", name, descriptor, policy)
return null
}
- if (!shouldEmit(p.policy)) {
+ if (p.policy == FilterPolicy.Remove) {
log.d("Removing %s%s %s", name, descriptor, policy)
return null
}
@@ -209,13 +171,16 @@
// `name` is the name of the method we're currently visiting, so it's usually a
// "...$ravewnwood" name.
newAccess = checkSubstitutionMethodCompatibility(
- classes, currentClassName, newName, name, descriptor, options.errors)
+ classes, currentClassName, newName, name, descriptor, options.errors
+ )
if (newAccess == NOT_COMPATIBLE) {
return null
}
- log.v("Emitting %s.%s%s as %s %s", currentClassName, name, descriptor,
- newName, policy)
+ log.v(
+ "Emitting %s.%s%s as %s %s", currentClassName, name, descriptor,
+ newName, policy
+ )
} else {
log.v("Emitting method: %s%s %s", name, descriptor, policy)
newName = name
@@ -225,14 +190,17 @@
// But note, we only use it when calling the super's method,
// but not for visitMethodInner(), because when subclass wants to change access,
// it can do so inside visitMethodInner().
- newAccess = updateAccessFlags(newAccess, name, descriptor)
+ newAccess = updateAccessFlags(newAccess, name, descriptor, policy.policy)
- val ret = visitMethodInner(access, newName, descriptor, signature, exceptions, policy,
+ val ret = visitMethodInner(
+ access, newName, descriptor, signature, exceptions, policy,
renameTo != null,
- super.visitMethod(newAccess, newName, descriptor, signature, exceptions))
+ super.visitMethod(newAccess, newName, descriptor, signature, exceptions)
+ )
ret?.let {
- injectInStubAndKeepAnnotations(policy.policy, UnifiedVisitor.on(ret))
+ UnifiedVisitor.on(ret)
+ .visitAnnotation(HostStubGenProcessedAsKeep.CLASS_DESCRIPTOR, true)
}
return ret
@@ -240,9 +208,10 @@
}
open fun updateAccessFlags(
- access: Int,
- name: String,
- descriptor: String,
+ access: Int,
+ name: String,
+ descriptor: String,
+ policy: FilterPolicy,
): Int {
return access
}
@@ -256,7 +225,7 @@
policy: FilterPolicyWithReason,
substituted: Boolean,
superVisitor: MethodVisitor?,
- ): MethodVisitor?
+ ): MethodVisitor?
companion object {
fun getVisitor(
@@ -265,8 +234,6 @@
nextVisitor: ClassVisitor,
filter: OutputFilter,
packageRedirector: PackageRedirectRemapper,
- remapper: Remapper?,
- forImpl: Boolean,
options: Options,
): ClassVisitor {
var next = nextVisitor
@@ -289,23 +256,20 @@
if (!packageRedirector.isTarget(classInternalName)) {
next = ClassRemapper(next, packageRedirector)
} else {
- log.v("Class $classInternalName is a redirect-from class, not applying" +
- " --package-redirect")
+ log.v(
+ "Class $classInternalName is a redirect-from class, not applying" +
+ " --package-redirect"
+ )
}
}
- var ret: ClassVisitor
- if (forImpl) {
- ret = ImplGeneratingAdapter(classes, next, filter, options)
- } else {
- ret = StubGeneratingAdapter(classes, next, filter, options)
- }
+ next = ImplGeneratingAdapter(classes, next, filter, options)
// Inject TraceClassVisitor for debugging.
if (options.enablePreTrace) {
- ret = TraceClassVisitor(ret, verbosePrinter)
+ next = TraceClassVisitor(next, verbosePrinter)
}
- return ret
+ return next
}
}
}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt
index 8250412..55d0c0e 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BodyReplacingMethodVisitor.kt
@@ -20,38 +20,23 @@
import org.objectweb.asm.Handle
import org.objectweb.asm.Label
import org.objectweb.asm.MethodVisitor
-import org.objectweb.asm.Opcodes
import org.objectweb.asm.TypePath
/**
- * A method visitor that removes everything from method body.
+ * A method visitor that creates or replaces a method body.
*
- * To inject a method body, override [visitCode] and create the opcodes there.
+ * Override [emitNewCode] to build the method body.
*/
abstract class BodyReplacingMethodVisitor(
- access: Int,
- name: String,
- descriptor: String,
- signature: String?,
- exceptions: Array<String>?,
- next: MethodVisitor?,
+ private val createBody: Boolean,
+ next: MethodVisitor?
) : MethodVisitor(OPCODE_VERSION, next) {
- val isVoid: Boolean
- val isStatic: Boolean
-
- init {
- isVoid = descriptor.endsWith(")V")
- isStatic = access and Opcodes.ACC_STATIC != 0
- }
// Following methods are for things that we need to keep.
// Since they're all calling the super method, we can just remove them, but we keep them
// just to clarify what we're keeping.
- final override fun visitParameter(
- name: String?,
- access: Int
- ) {
+ final override fun visitParameter(name: String?, access: Int) {
super.visitParameter(name, access)
}
@@ -59,10 +44,7 @@
return super.visitAnnotationDefault()
}
- final override fun visitAnnotation(
- descriptor: String?,
- visible: Boolean
- ): AnnotationVisitor? {
+ final override fun visitAnnotation(descriptor: String?, visible: Boolean): AnnotationVisitor? {
return super.visitAnnotation(descriptor, visible)
}
@@ -75,17 +57,14 @@
return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible)
}
- final override fun visitAnnotableParameterCount(
- parameterCount: Int,
- visible: Boolean
- ) {
+ final override fun visitAnnotableParameterCount(parameterCount: Int, visible: Boolean) {
super.visitAnnotableParameterCount(parameterCount, visible)
}
final override fun visitParameterAnnotation(
- parameter: Int,
- descriptor: String?,
- visible: Boolean
+ parameter: Int,
+ descriptor: String?,
+ visible: Boolean
): AnnotationVisitor? {
return super.visitParameterAnnotation(parameter, descriptor, visible)
}
@@ -94,10 +73,6 @@
super.visitAttribute(attribute)
}
- override fun visitEnd() {
- super.visitEnd()
- }
-
/**
* Control when to emit the code. We use this to ignore all visitXxx method calls caused by
* the original method, so we'll remove all the original code.
@@ -108,9 +83,18 @@
* (See also https://asm.ow2.io/asm4-guide.pdf section 3.2.1 about the MethovVisitor
* call order.)
*/
- var emitCode = false
+ private var emitCode = false
+
+ /**
+ * This value will be set as true when [visitCode] is called. In [visitEnd], if this value
+ * is still false, this means that the original method does not have a body.
+ *
+ * We want to forcefully inject a method body in [visitEnd] if [createBody] is true.
+ */
+ private var visitedCode = false
final override fun visitCode() {
+ visitedCode = true
super.visitCode()
try {
@@ -122,15 +106,19 @@
}
}
+ final override fun visitEnd() {
+ if (!visitedCode && createBody) {
+ visitCode()
+ }
+ super.visitEnd()
+ }
+
/**
* Subclass must implement it and emit code, and call [visitMaxs] at the end.
*/
abstract fun emitNewCode()
- final override fun visitMaxs(
- maxStack: Int,
- maxLocals: Int
- ) {
+ final override fun visitMaxs(maxStack: Int, maxLocals: Int) {
if (emitCode) {
super.visitMaxs(maxStack, maxLocals)
}
@@ -140,11 +128,11 @@
// emit any of them, so they are all no-op.
final override fun visitFrame(
- type: Int,
- numLocal: Int,
- local: Array<out Any>?,
- numStack: Int,
- stack: Array<out Any>?
+ type: Int,
+ numLocal: Int,
+ local: Array<out Any>?,
+ numStack: Int,
+ stack: Array<out Any>?
) {
if (emitCode) {
super.visitFrame(type, numLocal, local, numStack, stack)
@@ -157,38 +145,29 @@
}
}
- final override fun visitIntInsn(
- opcode: Int,
- operand: Int
- ) {
+ final override fun visitIntInsn(opcode: Int, operand: Int) {
if (emitCode) {
super.visitIntInsn(opcode, operand)
}
}
- final override fun visitVarInsn(
- opcode: Int,
- varIndex: Int
- ) {
+ final override fun visitVarInsn(opcode: Int, varIndex: Int) {
if (emitCode) {
super.visitVarInsn(opcode, varIndex)
}
}
- final override fun visitTypeInsn(
- opcode: Int,
- type: String?
- ) {
+ final override fun visitTypeInsn(opcode: Int, type: String?) {
if (emitCode) {
super.visitTypeInsn(opcode, type)
}
}
final override fun visitFieldInsn(
- opcode: Int,
- owner: String?,
- name: String?,
- descriptor: String?
+ opcode: Int,
+ owner: String?,
+ name: String?,
+ descriptor: String?
) {
if (emitCode) {
super.visitFieldInsn(opcode, owner, name, descriptor)
@@ -196,11 +175,11 @@
}
final override fun visitMethodInsn(
- opcode: Int,
- owner: String?,
- name: String?,
- descriptor: String?,
- isInterface: Boolean
+ opcode: Int,
+ owner: String?,
+ name: String?,
+ descriptor: String?,
+ isInterface: Boolean
) {
if (emitCode) {
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
@@ -208,21 +187,20 @@
}
final override fun visitInvokeDynamicInsn(
- name: String?,
- descriptor: String?,
- bootstrapMethodHandle: Handle?,
- vararg bootstrapMethodArguments: Any?
+ name: String?,
+ descriptor: String?,
+ bootstrapMethodHandle: Handle?,
+ vararg bootstrapMethodArguments: Any?
) {
if (emitCode) {
- super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle,
- *bootstrapMethodArguments)
+ super.visitInvokeDynamicInsn(
+ name, descriptor, bootstrapMethodHandle,
+ *bootstrapMethodArguments
+ )
}
}
- final override fun visitJumpInsn(
- opcode: Int,
- label: Label?
- ) {
+ final override fun visitJumpInsn(opcode: Int, label: Label?) {
if (emitCode) {
super.visitJumpInsn(opcode, label)
}
@@ -240,20 +218,17 @@
}
}
- final override fun visitIincInsn(
- varIndex: Int,
- increment: Int
- ) {
+ final override fun visitIincInsn(varIndex: Int, increment: Int) {
if (emitCode) {
super.visitIincInsn(varIndex, increment)
}
}
final override fun visitTableSwitchInsn(
- min: Int,
- max: Int,
- dflt: Label?,
- vararg labels: Label?
+ min: Int,
+ max: Int,
+ dflt: Label?,
+ vararg labels: Label?
) {
if (emitCode) {
super.visitTableSwitchInsn(min, max, dflt, *labels)
@@ -261,29 +236,26 @@
}
final override fun visitLookupSwitchInsn(
- dflt: Label?,
- keys: IntArray?,
- labels: Array<out Label>?
+ dflt: Label?,
+ keys: IntArray?,
+ labels: Array<out Label>?
) {
if (emitCode) {
super.visitLookupSwitchInsn(dflt, keys, labels)
}
}
- final override fun visitMultiANewArrayInsn(
- descriptor: String?,
- numDimensions: Int
- ) {
+ final override fun visitMultiANewArrayInsn(descriptor: String?, numDimensions: Int) {
if (emitCode) {
super.visitMultiANewArrayInsn(descriptor, numDimensions)
}
}
final override fun visitInsnAnnotation(
- typeRef: Int,
- typePath: TypePath?,
- descriptor: String?,
- visible: Boolean
+ typeRef: Int,
+ typePath: TypePath?,
+ descriptor: String?,
+ visible: Boolean
): AnnotationVisitor? {
if (emitCode) {
return super.visitInsnAnnotation(typeRef, typePath, descriptor, visible)
@@ -292,10 +264,10 @@
}
final override fun visitTryCatchBlock(
- start: Label?,
- end: Label?,
- handler: Label?,
- type: String?
+ start: Label?,
+ end: Label?,
+ handler: Label?,
+ type: String?
) {
if (emitCode) {
super.visitTryCatchBlock(start, end, handler, type)
@@ -303,10 +275,10 @@
}
final override fun visitTryCatchAnnotation(
- typeRef: Int,
- typePath: TypePath?,
- descriptor: String?,
- visible: Boolean
+ typeRef: Int,
+ typePath: TypePath?,
+ descriptor: String?,
+ visible: Boolean
): AnnotationVisitor? {
if (emitCode) {
return super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible)
@@ -315,12 +287,12 @@
}
final override fun visitLocalVariable(
- name: String?,
- descriptor: String?,
- signature: String?,
- start: Label?,
- end: Label?,
- index: Int
+ name: String?,
+ descriptor: String?,
+ signature: String?,
+ start: Label?,
+ end: Label?,
+ index: Int
) {
if (emitCode) {
super.visitLocalVariable(name, descriptor, signature, start, end, index)
@@ -328,25 +300,23 @@
}
final override fun visitLocalVariableAnnotation(
- typeRef: Int,
- typePath: TypePath?,
- start: Array<out Label>?,
- end: Array<out Label>?,
- index: IntArray?,
- descriptor: String?,
- visible: Boolean
+ typeRef: Int,
+ typePath: TypePath?,
+ start: Array<out Label>?,
+ end: Array<out Label>?,
+ index: IntArray?,
+ descriptor: String?,
+ visible: Boolean
): AnnotationVisitor? {
if (emitCode) {
return super.visitLocalVariableAnnotation(
- typeRef, typePath, start, end, index, descriptor, visible)
+ typeRef, typePath, start, end, index, descriptor, visible
+ )
}
return null
}
- final override fun visitLineNumber(
- line: Int,
- start: Label?
- ) {
+ final override fun visitLineNumber(line: Int, start: Label?) {
if (emitCode) {
super.visitLineNumber(line, start)
}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
index 3d2e142..567a69e 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/ImplGeneratingAdapter.kt
@@ -18,7 +18,6 @@
import com.android.hoststubgen.asm.CLASS_INITIALIZER_DESC
import com.android.hoststubgen.asm.CLASS_INITIALIZER_NAME
import com.android.hoststubgen.asm.ClassNodes
-import com.android.hoststubgen.asm.isVisibilityPrivateOrPackagePrivate
import com.android.hoststubgen.asm.prependArgTypeToMethodDescriptor
import com.android.hoststubgen.asm.writeByteCodeToPushArguments
import com.android.hoststubgen.asm.writeByteCodeToReturn
@@ -42,16 +41,12 @@
* An adapter that generates the "impl" class file from an input class file.
*/
class ImplGeneratingAdapter(
- classes: ClassNodes,
- nextVisitor: ClassVisitor,
- filter: OutputFilter,
- options: Options,
+ classes: ClassNodes,
+ nextVisitor: ClassVisitor,
+ filter: OutputFilter,
+ options: Options,
) : BaseAdapter(classes, nextVisitor, filter, options) {
- override fun shouldEmit(policy: FilterPolicy): Boolean {
- return policy.needsInImpl
- }
-
private var classLoadHooks: List<String> = emptyList()
override fun visit(
@@ -107,14 +102,14 @@
private fun writeClassLoadHookCalls(mv: MethodVisitor) {
classLoadHooks.forEach { classLoadHook ->
// First argument: the class type.
- mv.visitLdcInsn(Type.getType("L" + currentClassName + ";"))
+ mv.visitLdcInsn(Type.getType("L$currentClassName;"))
// Second argument: method name
mv.visitLdcInsn(classLoadHook)
// Call HostTestUtils.onClassLoaded().
mv.visitMethodInsn(
- Opcodes.INVOKESTATIC,
+ INVOKESTATIC,
HostTestUtils.CLASS_INTERNAL_NAME,
"onClassLoaded",
"(Ljava/lang/Class;Ljava/lang/String;)V",
@@ -124,69 +119,49 @@
}
override fun updateAccessFlags(
- access: Int,
- name: String,
- descriptor: String,
+ access: Int,
+ name: String,
+ descriptor: String,
+ policy: FilterPolicy,
): Int {
- if ((access and Opcodes.ACC_NATIVE) != 0 && nativeSubstitutionClass != null) {
+ if (policy.isMethodRewriteBody) {
+ // If we are rewriting the entire method body, we need
+ // to convert native methods to non-native
return access and Opcodes.ACC_NATIVE.inv()
}
return access
}
override fun visitMethodInner(
- access: Int,
- name: String,
- descriptor: String,
- signature: String?,
- exceptions: Array<String>?,
- policy: FilterPolicyWithReason,
- substituted: Boolean,
- superVisitor: MethodVisitor?,
+ access: Int,
+ name: String,
+ descriptor: String,
+ signature: String?,
+ exceptions: Array<String>?,
+ policy: FilterPolicyWithReason,
+ substituted: Boolean,
+ superVisitor: MethodVisitor?,
): MethodVisitor? {
- // Inject method log, if needed.
var innerVisitor = superVisitor
// If method logging is enabled, inject call to the logging method.
val methodCallHooks = filter.getMethodCallHooks(currentClassName, name, descriptor)
if (methodCallHooks.isNotEmpty()) {
innerVisitor = MethodCallHookInjectingAdapter(
- access,
name,
descriptor,
- signature,
- exceptions,
- innerVisitor,
methodCallHooks,
- )
+ innerVisitor,
+ )
}
// If this class already has a class initializer and a class load hook is needed, then
// we inject code.
if (classLoadHooks.isNotEmpty() &&
name == CLASS_INITIALIZER_NAME &&
- descriptor == CLASS_INITIALIZER_DESC) {
- innerVisitor = ClassLoadHookInjectingMethodAdapter(
- access,
- name,
- descriptor,
- signature,
- exceptions,
- innerVisitor,
- )
- }
-
- // If non-stub method call detection is enabled, then inject a call to the checker.
- if (options.enableNonStubMethodCallDetection && doesMethodNeedNonStubCallCheck(
- access, name, descriptor, policy) ) {
- innerVisitor = NonStubMethodCallDetectingAdapter(
- access,
- name,
- descriptor,
- signature,
- exceptions,
- innerVisitor,
- )
+ descriptor == CLASS_INITIALIZER_DESC
+ ) {
+ innerVisitor = ClassLoadHookInjectingMethodAdapter(innerVisitor)
}
fun MethodVisitor.withAnnotation(descriptor: String): MethodVisitor {
@@ -195,34 +170,34 @@
}
log.withIndent {
- var willThrow = false
- if (policy.policy == FilterPolicy.Throw) {
- log.v("Making method throw...")
- willThrow = true
- innerVisitor = ThrowingMethodAdapter(
- access, name, descriptor, signature, exceptions, innerVisitor)
- .withAnnotation(HostStubGenProcessedAsThrow.CLASS_DESCRIPTOR)
+ // When we encounter native methods, we want to forcefully
+ // inject a method body. Also see [updateAccessFlags].
+ val forceCreateBody = (access and Opcodes.ACC_NATIVE) != 0
+ when (policy.policy) {
+ FilterPolicy.Throw -> {
+ log.v("Making method throw...")
+ return ThrowingMethodAdapter(forceCreateBody, innerVisitor)
+ .withAnnotation(HostStubGenProcessedAsThrow.CLASS_DESCRIPTOR)
+ }
+ FilterPolicy.Ignore -> {
+ log.v("Making method ignored...")
+ return IgnoreMethodAdapter(descriptor, forceCreateBody, innerVisitor)
+ .withAnnotation(HostStubGenProcessedAsIgnore.CLASS_DESCRIPTOR)
+ }
+ FilterPolicy.Redirect -> {
+ log.v("Redirecting method...")
+ return RedirectMethodAdapter(
+ access, name, descriptor,
+ forceCreateBody, innerVisitor
+ )
+ .withAnnotation(HostStubGenProcessedAsSubstitute.CLASS_DESCRIPTOR)
+ }
+ else -> {}
}
- if ((access and Opcodes.ACC_NATIVE) != 0 && nativeSubstitutionClass != null) {
- log.v("Rewriting native method...")
- return NativeSubstitutingMethodAdapter(
- access, name, descriptor, signature, exceptions, innerVisitor)
- .withAnnotation(HostStubGenProcessedAsSubstitute.CLASS_DESCRIPTOR)
- }
- if (willThrow) {
- return innerVisitor
- }
+ }
- if (policy.policy == FilterPolicy.Ignore) {
- log.v("Making method ignored...")
- return IgnoreMethodAdapter(
- access, name, descriptor, signature, exceptions, innerVisitor)
- .withAnnotation(HostStubGenProcessedAsIgnore.CLASS_DESCRIPTOR)
- }
- if (filter.hasAnyMethodCallReplace()) {
- innerVisitor = MethodCallReplacingAdapter(
- access, name, descriptor, signature, exceptions, innerVisitor)
- }
+ if (filter.hasAnyMethodCallReplace()) {
+ innerVisitor = MethodCallReplacingAdapter(name, innerVisitor)
}
if (substituted) {
innerVisitor?.withAnnotation(HostStubGenProcessedAsSubstitute.CLASS_DESCRIPTOR)
@@ -231,53 +206,32 @@
return innerVisitor
}
- fun doesMethodNeedNonStubCallCheck(
- access: Int,
- name: String,
- descriptor: String,
- policy: FilterPolicyWithReason,
- ): Boolean {
- // If a method is in the stub, then no need to check.
- if (policy.policy.needsInStub) {
- return false
- }
- // If a method is private or package-private, no need to check.
- // Technically test code can use framework package name, so it's a bit too lenient.
- if (isVisibilityPrivateOrPackagePrivate(access)) {
- return false
- }
- // TODO: If the method overrides a method that's accessible by tests, then we shouldn't
- // do the check. (e.g. overrides a stub method or java standard method.)
-
- return true
- }
-
/**
* A method adapter that replaces the method body with a HostTestUtils.onThrowMethodCalled()
* call.
*/
private inner class ThrowingMethodAdapter(
- access: Int,
- val name: String,
- descriptor: String,
- signature: String?,
- exceptions: Array<String>?,
- next: MethodVisitor?
- ) : BodyReplacingMethodVisitor(access, name, descriptor, signature, exceptions, next) {
+ createBody: Boolean,
+ next: MethodVisitor?
+ ) : BodyReplacingMethodVisitor(createBody, next) {
override fun emitNewCode() {
- visitMethodInsn(Opcodes.INVOKESTATIC,
- HostTestUtils.CLASS_INTERNAL_NAME,
- "onThrowMethodCalled",
- "()V",
- false)
+ visitMethodInsn(
+ INVOKESTATIC,
+ HostTestUtils.CLASS_INTERNAL_NAME,
+ "onThrowMethodCalled",
+ "()V",
+ false
+ )
// We still need a RETURN opcode for the return type.
// For now, let's just inject a `throw`.
visitTypeInsn(Opcodes.NEW, "java/lang/RuntimeException")
visitInsn(Opcodes.DUP)
visitLdcInsn("Unreachable")
- visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/RuntimeException",
- "<init>", "(Ljava/lang/String;)V", false)
+ visitMethodInsn(
+ Opcodes.INVOKESPECIAL, "java/lang/RuntimeException",
+ "<init>", "(Ljava/lang/String;)V", false
+ )
visitInsn(Opcodes.ATHROW)
// visitMaxs(3, if (isStatic) 0 else 1)
@@ -289,13 +243,10 @@
* A method adapter that replaces the method body with a no-op return.
*/
private inner class IgnoreMethodAdapter(
- access: Int,
- name: String,
- val descriptor: String,
- signature: String?,
- exceptions: Array<String>?,
- next: MethodVisitor?
- ) : BodyReplacingMethodVisitor(access, name, descriptor, signature, exceptions, next) {
+ val descriptor: String,
+ createBody: Boolean,
+ next: MethodVisitor?
+ ) : BodyReplacingMethodVisitor(createBody, next) {
override fun emitNewCode() {
when (Type.getReturnType(descriptor)) {
Type.VOID_TYPE -> visitInsn(Opcodes.RETURN)
@@ -326,30 +277,25 @@
}
/**
- * A method adapter that replaces a native method call with a call to the "native substitution"
- * class.
+ * A method adapter that rewrite a method body with a
+ * call to a method in the redirection class.
*/
- private inner class NativeSubstitutingMethodAdapter(
- val access: Int,
- private val name: String,
- private val descriptor: String,
- signature: String?,
- exceptions: Array<String>?,
- next: MethodVisitor?
- ) : MethodVisitor(OPCODE_VERSION, next) {
- override fun visitCode() {
- throw RuntimeException("NativeSubstitutingMethodVisitor should be called on " +
- " native method, where visitCode() shouldn't be called.")
- }
+ private inner class RedirectMethodAdapter(
+ access: Int,
+ private val name: String,
+ private val descriptor: String,
+ createBody: Boolean,
+ next: MethodVisitor?
+ ) : BodyReplacingMethodVisitor(createBody, next) {
- override fun visitEnd() {
- super.visitCode()
+ private val isStatic = (access and Opcodes.ACC_STATIC) != 0
+ override fun emitNewCode() {
var targetDescriptor = descriptor
var argOffset = 0
- // For non-static native method, we need to tweak it a bit.
- if ((access and Opcodes.ACC_STATIC) == 0) {
+ // For non-static method, we need to tweak it a bit.
+ if (!isStatic) {
// Push `this` as the first argument.
this.visitVarInsn(Opcodes.ALOAD, 0)
@@ -366,16 +312,17 @@
writeByteCodeToPushArguments(descriptor, this, argOffset)
- visitMethodInsn(Opcodes.INVOKESTATIC,
- nativeSubstitutionClass,
- name,
- targetDescriptor,
- false)
+ visitMethodInsn(
+ INVOKESTATIC,
+ redirectionClass,
+ name,
+ targetDescriptor,
+ false
+ )
writeByteCodeToReturn(descriptor, this)
visitMaxs(99, 0) // We let ASM figure them out.
- super.visitEnd()
}
}
@@ -386,25 +333,22 @@
* `this(...)`. The logging code will be injected *before* such calls.
*/
private inner class MethodCallHookInjectingAdapter(
- access: Int,
- val name: String,
- val descriptor: String,
- signature: String?,
- exceptions: Array<String>?,
- next: MethodVisitor?,
- val hooks: List<String>,
+ val name: String,
+ val descriptor: String,
+ val hooks: List<String>,
+ next: MethodVisitor?,
) : MethodVisitor(OPCODE_VERSION, next) {
override fun visitCode() {
super.visitCode()
hooks.forEach { hook ->
- mv.visitLdcInsn(Type.getType("L" + currentClassName + ";"))
+ mv.visitLdcInsn(Type.getType("L$currentClassName;"))
visitLdcInsn(name)
visitLdcInsn(descriptor)
visitLdcInsn(hook)
visitMethodInsn(
- Opcodes.INVOKESTATIC,
+ INVOKESTATIC,
HostTestUtils.CLASS_INTERNAL_NAME,
"callMethodCallHook",
"(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
@@ -418,11 +362,6 @@
* Inject a class load hook call.
*/
private inner class ClassLoadHookInjectingMethodAdapter(
- access: Int,
- val name: String,
- val descriptor: String,
- signature: String?,
- exceptions: Array<String>?,
next: MethodVisitor?
) : MethodVisitor(OPCODE_VERSION, next) {
override fun visitCode() {
@@ -432,53 +371,8 @@
}
}
- /**
- * A method adapter that detects calls to non-stub methods.
- */
- private inner class NonStubMethodCallDetectingAdapter(
- access: Int,
- val name: String,
- val descriptor: String,
- signature: String?,
- exceptions: Array<String>?,
- next: MethodVisitor?
- ) : MethodVisitor(OPCODE_VERSION, next) {
- override fun visitCode() {
- super.visitCode()
-
- // First three arguments to HostTestUtils.onNonStubMethodCalled().
- visitLdcInsn(currentClassName)
- visitLdcInsn(name)
- visitLdcInsn(descriptor)
-
- // Call: HostTestUtils.getStackWalker().getCallerClass().
- // This push the caller Class in the stack.
- visitMethodInsn(Opcodes.INVOKESTATIC,
- HostTestUtils.CLASS_INTERNAL_NAME,
- "getStackWalker",
- "()Ljava/lang/StackWalker;",
- false)
- visitMethodInsn(Opcodes.INVOKEVIRTUAL,
- "java/lang/StackWalker",
- "getCallerClass",
- "()Ljava/lang/Class;",
- false)
-
- // Then call onNonStubMethodCalled().
- visitMethodInsn(Opcodes.INVOKESTATIC,
- HostTestUtils.CLASS_INTERNAL_NAME,
- "onNonStubMethodCalled",
- "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V",
- false)
- }
- }
-
private inner class MethodCallReplacingAdapter(
- access: Int,
val callerMethodName: String,
- val descriptor: String,
- signature: String?,
- exceptions: Array<String>?,
next: MethodVisitor?,
) : MethodVisitor(OPCODE_VERSION, next) {
override fun visitMethodInsn(
@@ -497,7 +391,8 @@
}
}
val to = filter.getMethodCallReplaceTo(
- currentClassName, callerMethodName, owner!!, name!!, descriptor!!)
+ currentClassName, callerMethodName, owner!!, name!!, descriptor!!
+ )
if (to == null
// Don't replace if the target is the callsite.
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt
deleted file mode 100644
index fc20f28..0000000
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/StubGeneratingAdapter.kt
+++ /dev/null
@@ -1,86 +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.hoststubgen.visitors
-
-import com.android.hoststubgen.asm.ClassNodes
-import com.android.hoststubgen.filters.FilterPolicy
-import com.android.hoststubgen.filters.FilterPolicyWithReason
-import com.android.hoststubgen.filters.OutputFilter
-import com.android.hoststubgen.log
-import org.objectweb.asm.ClassVisitor
-import org.objectweb.asm.MethodVisitor
-import org.objectweb.asm.Opcodes
-
-/**
- * An adapter that generates the "impl" class file from an input class file.
- */
-class StubGeneratingAdapter(
- classes: ClassNodes,
- nextVisitor: ClassVisitor,
- filter: OutputFilter,
- options: Options,
-) : BaseAdapter(classes, nextVisitor, filter, options) {
-
- override fun shouldEmit(policy: FilterPolicy): Boolean {
- return policy.needsInStub
- }
-
- override fun visitMethodInner(
- access: Int,
- name: String,
- descriptor: String,
- signature: String?,
- exceptions: Array<String>?,
- policy: FilterPolicyWithReason,
- substituted: Boolean,
- superVisitor: MethodVisitor?,
- ): MethodVisitor? {
- return StubMethodVisitor(access, name, descriptor, signature, exceptions, superVisitor)
- }
-
- private inner class StubMethodVisitor(
- access: Int,
- val name: String,
- descriptor: String,
- signature: String?,
- exceptions: Array<String>?,
- next: MethodVisitor?
- ) : BodyReplacingMethodVisitor(access, name, descriptor, signature, exceptions, next) {
- override fun emitNewCode() {
- log.d(" Generating stub method for $currentClassName.$name")
-
- // Inject the following code:
- // throw new RuntimeException("Stub!");
-
- /*
- NEW java/lang/RuntimeException
- DUP
- LDC "not supported on host side"
- INVOKESPECIAL java/lang/RuntimeException.<init> (Ljava/lang/String;)V
- ATHROW
- MAXSTACK = 3
- MAXLOCALS = 2 <- 1 for this, 1 for return value.
- */
- visitTypeInsn(Opcodes.NEW, "java/lang/RuntimeException")
- visitInsn(Opcodes.DUP)
- visitLdcInsn("Stub!")
- visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/RuntimeException",
- "<init>", "(Ljava/lang/String;)V", false)
- visitInsn(Opcodes.ATHROW)
- visitMaxs(0, 0) // We let ASM figure them out.
- }
- }
-}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp b/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp
index e7873d6..ba2c869 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/Android.bp
@@ -21,7 +21,7 @@
// Create stub/impl jars from "hoststubgen-test-tiny-framework", using the following 3 rules.
java_genrule_host {
- name: "hoststubgen-test-tiny-framework-host",
+ name: "hoststubgen-test-tiny-framework-host-base",
defaults: ["hoststubgen-command-defaults"],
cmd: hoststubgen_common_options +
"--in-jar $(location :hoststubgen-test-tiny-framework) " +
@@ -35,25 +35,13 @@
}
java_genrule_host {
- name: "hoststubgen-test-tiny-framework-host-stub",
+ name: "hoststubgen-test-tiny-framework-host",
cmd: "cp $(in) $(out)",
srcs: [
- ":hoststubgen-test-tiny-framework-host{host_stub.jar}",
+ ":hoststubgen-test-tiny-framework-host-base{host.jar}",
],
out: [
- "host_stub.jar",
- ],
- visibility: ["//visibility:private"],
-}
-
-java_genrule_host {
- name: "hoststubgen-test-tiny-framework-host-impl",
- cmd: "cp $(in) $(out)",
- srcs: [
- ":hoststubgen-test-tiny-framework-host{host_impl.jar}",
- ],
- out: [
- "host_impl.jar",
+ "host.jar",
],
visibility: ["//visibility:private"],
}
@@ -61,7 +49,7 @@
// Same as "hoststubgen-test-tiny-framework-host", but with more options, to test more hoststubgen
// features.
java_genrule_host {
- name: "hoststubgen-test-tiny-framework-host-ext",
+ name: "hoststubgen-test-tiny-framework-host-ext-base",
defaults: ["hoststubgen-command-defaults"],
cmd: hoststubgen_common_options +
"--in-jar $(location :hoststubgen-test-tiny-framework) " +
@@ -79,37 +67,25 @@
}
java_genrule_host {
- name: "hoststubgen-test-tiny-framework-host-ext-stub",
+ name: "hoststubgen-test-tiny-framework-host-ext",
cmd: "cp $(in) $(out)",
srcs: [
- ":hoststubgen-test-tiny-framework-host-ext{host_stub.jar}",
+ ":hoststubgen-test-tiny-framework-host-ext-base{host.jar}",
],
out: [
- "host_stub.jar",
- ],
- visibility: ["//visibility:private"],
-}
-
-java_genrule_host {
- name: "hoststubgen-test-tiny-framework-host-ext-impl",
- cmd: "cp $(in) $(out)",
- srcs: [
- ":hoststubgen-test-tiny-framework-host-ext{host_impl.jar}",
- ],
- out: [
- "host_impl.jar",
+ "host.jar",
],
visibility: ["//visibility:private"],
}
// Compile the test jar, using 2 rules.
-// 1. Build the test against the stub.
+// 1. Build the test against the original framework.
java_library_host {
name: "hoststubgen-test-tiny-test-lib",
srcs: ["tiny-test/src/**/*.java"],
libs: [
- "hoststubgen-test-tiny-framework-host-stub",
+ "hoststubgen-test-tiny-framework",
],
static_libs: [
"junit",
@@ -129,7 +105,7 @@
static_libs: [
"hoststubgen-test-tiny-test-lib",
"hoststubgen-helper-runtime",
- "hoststubgen-test-tiny-framework-host-impl",
+ "hoststubgen-test-tiny-framework-host",
],
test_suites: ["general-tests"],
}
@@ -149,49 +125,25 @@
}
java_genrule_host {
- name: "hoststubgen-test-tiny-framework-host-stub-dump",
+ name: "hoststubgen-test-tiny-framework-host-dump",
defaults: ["hoststubgen-jar-dump-defaults"],
srcs: [
- ":hoststubgen-test-tiny-framework-host-stub",
+ ":hoststubgen-test-tiny-framework-host",
],
out: [
- "02-hoststubgen-test-tiny-framework-host-stub-dump.txt",
+ "03-hoststubgen-test-tiny-framework-host-dump.txt",
],
visibility: ["//visibility:private"],
}
java_genrule_host {
- name: "hoststubgen-test-tiny-framework-host-impl-dump",
+ name: "hoststubgen-test-tiny-framework-host-ext-dump",
defaults: ["hoststubgen-jar-dump-defaults"],
srcs: [
- ":hoststubgen-test-tiny-framework-host-impl",
+ ":hoststubgen-test-tiny-framework-host-ext",
],
out: [
- "03-hoststubgen-test-tiny-framework-host-impl-dump.txt",
- ],
- visibility: ["//visibility:private"],
-}
-
-java_genrule_host {
- name: "hoststubgen-test-tiny-framework-host-ext-stub-dump",
- defaults: ["hoststubgen-jar-dump-defaults"],
- srcs: [
- ":hoststubgen-test-tiny-framework-host-ext-stub",
- ],
- out: [
- "12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt",
- ],
- visibility: ["//visibility:private"],
-}
-
-java_genrule_host {
- name: "hoststubgen-test-tiny-framework-host-ext-impl-dump",
- defaults: ["hoststubgen-jar-dump-defaults"],
- srcs: [
- ":hoststubgen-test-tiny-framework-host-ext-impl",
- ],
- out: [
- "13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt",
+ "13-hoststubgen-test-tiny-framework-host-ext-dump.txt",
],
visibility: ["//visibility:private"],
}
@@ -206,11 +158,9 @@
"golden-output/*.txt",
],
java_data: [
- "hoststubgen-test-tiny-framework-host-stub-dump",
- "hoststubgen-test-tiny-framework-host-impl-dump",
"hoststubgen-test-tiny-framework-orig-dump",
- "hoststubgen-test-tiny-framework-host-ext-stub-dump",
- "hoststubgen-test-tiny-framework-host-ext-impl-dump",
+ "hoststubgen-test-tiny-framework-host-dump",
+ "hoststubgen-test-tiny-framework-host-ext-dump",
],
test_suites: ["general-tests"],
}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
index 845e1d0..82586bb 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/01-hoststubgen-test-tiny-framework-orig-dump.txt
@@ -41,20 +41,40 @@
java.lang.annotation.Retention(
value=Ljava/lang/annotation/RetentionPolicy;.CLASS
)
-## Class: android/hosttest/annotation/HostSideTestNativeSubstitutionClass.class
- Compiled from "HostSideTestNativeSubstitutionClass.java"
-public interface android.hosttest.annotation.HostSideTestNativeSubstitutionClass extends java.lang.annotation.Annotation
+## Class: android/hosttest/annotation/HostSideTestRedirect.class
+ Compiled from "HostSideTestRedirect.java"
+public interface android.hosttest.annotation.HostSideTestRedirect extends java.lang.annotation.Annotation
minor version: 0
major version: 61
flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
- this_class: #x // android/hosttest/annotation/HostSideTestNativeSubstitutionClass
+ this_class: #x // android/hosttest/annotation/HostSideTestRedirect
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestRedirect.java"
+RuntimeVisibleAnnotations:
+ x: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.METHOD]
+ )
+ x: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestRedirectionClass.class
+ Compiled from "HostSideTestRedirectionClass.java"
+public interface android.hosttest.annotation.HostSideTestRedirectionClass extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestRedirectionClass
super_class: #x // java/lang/Object
interfaces: 1, fields: 0, methods: 1, attributes: 2
public abstract java.lang.String value();
descriptor: ()Ljava/lang/String;
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
}
-SourceFile: "HostSideTestNativeSubstitutionClass.java"
+SourceFile: "HostSideTestRedirectionClass.java"
RuntimeVisibleAnnotations:
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
@@ -104,26 +124,6 @@
java.lang.annotation.Retention(
value=Ljava/lang/annotation/RetentionPolicy;.CLASS
)
-## Class: android/hosttest/annotation/HostSideTestStub.class
- Compiled from "HostSideTestStub.java"
-public interface android.hosttest.annotation.HostSideTestStub extends java.lang.annotation.Annotation
- minor version: 0
- major version: 61
- flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
- this_class: #x // android/hosttest/annotation/HostSideTestStub
- super_class: #x // java/lang/Object
- interfaces: 1, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "HostSideTestStub.java"
-RuntimeVisibleAnnotations:
- x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
- java.lang.annotation.Target(
- value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
- )
- x: #x(#x=e#x.#x)
- java.lang.annotation.Retention(
- value=Ljava/lang/annotation/RetentionPolicy;.CLASS
- )
## Class: android/hosttest/annotation/HostSideTestSubstitute.class
Compiled from "HostSideTestSubstitute.java"
public interface android.hosttest.annotation.HostSideTestSubstitute extends java.lang.annotation.Annotation
@@ -187,26 +187,6 @@
java.lang.annotation.Retention(
value=Ljava/lang/annotation/RetentionPolicy;.CLASS
)
-## Class: android/hosttest/annotation/HostSideTestWholeClassStub.class
- Compiled from "HostSideTestWholeClassStub.java"
-public interface android.hosttest.annotation.HostSideTestWholeClassStub extends java.lang.annotation.Annotation
- minor version: 0
- major version: 61
- flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
- this_class: #x // android/hosttest/annotation/HostSideTestWholeClassStub
- super_class: #x // java/lang/Object
- interfaces: 1, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "HostSideTestWholeClassStub.java"
-RuntimeVisibleAnnotations:
- x: #x(#x=[e#x.#x])
- java.lang.annotation.Target(
- value=[Ljava/lang/annotation/ElementType;.TYPE]
- )
- x: #x(#x=e#x.#x)
- java.lang.annotation.Retention(
- value=Ljava/lang/annotation/RetentionPolicy;.CLASS
- )
## Class: android/hosttest/annotation/tests/HostSideTestSuppress.class
Compiled from "HostSideTestSuppress.java"
public interface android.hosttest.annotation.tests.HostSideTestSuppress extends java.lang.annotation.Annotation
@@ -402,14 +382,7 @@
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
super_class: #x // java/lang/Object
- interfaces: 0, fields: 3, methods: 10, attributes: 2
- public int stub;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
+ interfaces: 0, fields: 2, methods: 8, attributes: 2
public int keep;
descriptor: I
flags: (0x0001) ACC_PUBLIC
@@ -430,42 +403,21 @@
x: invokespecial #x // Method java/lang/Object."<init>":()V
x: aload_0
x: iconst_1
- x: putfield #x // Field stub:I
- x: aload_0
- x: iconst_2
- x: putfield #x // Field keep:I
- x: return
+ x: putfield #x // Field keep:I
+ x: return
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public int addOne(int);
descriptor: (I)I
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
- x: aload_0
- x: iload_1
- x: invokevirtual #x // Method addOneInner:(I)I
- x: ireturn
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
- 0 6 1 value I
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public int addOneInner(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=2, locals=2, args_size=2
x: iload_1
x: iconst_1
x: iadd
@@ -513,8 +465,6 @@
0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
0 10 1 value I
RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
x: #x(#x=s#x)
android.hosttest.annotation.HostSideTestSubstitute(
suffix="_host"
@@ -539,8 +489,6 @@
descriptor: (I)I
flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
x: #x(#x=s#x)
android.hosttest.annotation.HostSideTestSubstitute(
suffix="_host"
@@ -574,129 +522,15 @@
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestThrow
-
- public java.lang.String visibleButUsesUnsupportedMethod();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=1, locals=1, args_size=1
- x: aload_0
- x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
- x: areturn
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
}
SourceFile: "TinyFrameworkAnnotations.java"
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
x: #x(#x=s#x)
android.hosttest.annotation.HostSideTestClassLoadHook(
value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
)
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
- Compiled from "TinyFrameworkCallerCheck.java"
-class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
- minor version: 0
- major version: 61
- flags: (0x0020) ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 3, attributes: 3
- private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
- descriptor: ()V
- flags: (0x0002) ACC_PRIVATE
- Code:
- stack=1, locals=1, args_size=1
- x: aload_0
- x: invokespecial #x // Method java/lang/Object."<init>":()V
- x: return
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl;
-
- public static int getOneKeep();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=1, locals=0, args_size=0
- x: iconst_1
- x: ireturn
- LineNumberTable:
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestKeep
-
- public static int getOneStub();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=1, locals=0, args_size=0
- x: iconst_1
- x: ireturn
- LineNumberTable:
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-}
-SourceFile: "TinyFrameworkCallerCheck.java"
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-InnerClasses:
- private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
- Compiled from "TinyFrameworkCallerCheck.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 3, attributes: 4
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=1, locals=1, args_size=1
- x: aload_0
- x: invokespecial #x // Method java/lang/Object."<init>":()V
- x: return
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck;
-
- public static int getOne_withCheck();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=1, locals=0, args_size=0
- x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneKeep:()I
- x: ireturn
- LineNumberTable:
-
- public static int getOne_noCheck();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=1, locals=0, args_size=0
- x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneStub:()I
- x: ireturn
- LineNumberTable:
-}
-SourceFile: "TinyFrameworkCallerCheck.java"
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-NestMembers:
- com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
-InnerClasses:
- private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
Compiled from "TinyFrameworkClassLoadHook.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
@@ -758,7 +592,7 @@
SourceFile: "TinyFrameworkClassLoadHook.java"
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.class
Compiled from "TinyFrameworkClassWideAnnotations.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations
@@ -767,11 +601,18 @@
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations
super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 6, attributes: 2
- public int stub;
+ interfaces: 0, fields: 2, methods: 6, attributes: 2
+ public int keep;
descriptor: I
flags: (0x0001) ACC_PUBLIC
+ public int remove;
+ descriptor: I
+ flags: (0x0001) ACC_PUBLIC
+ RuntimeInvisibleAnnotations:
+ x: #x()
+ android.hosttest.annotation.HostSideTestRemove
+
public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
@@ -781,7 +622,7 @@
x: invokespecial #x // Method java/lang/Object."<init>":()V
x: aload_0
x: iconst_1
- x: putfield #x // Field stub:I
+ x: putfield #x // Field keep:I
x: return
LineNumberTable:
LocalVariableTable:
@@ -839,6 +680,24 @@
0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations;
0 4 1 value I
+ public void toBeRemoved(java.lang.String);
+ descriptor: (Ljava/lang/String;)V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=2, args_size=2
+ x: new #x // class java/lang/RuntimeException
+ x: dup
+ x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V
+ x: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations;
+ 0 8 1 foo Ljava/lang/String;
+ RuntimeInvisibleAnnotations:
+ x: #x()
+ android.hosttest.annotation.HostSideTestRemove
+
public java.lang.String unsupportedMethod();
descriptor: ()Ljava/lang/String;
flags: (0x0001) ACC_PUBLIC
@@ -853,24 +712,11 @@
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestThrow
-
- public java.lang.String visibleButUsesUnsupportedMethod();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=1, locals=1, args_size=1
- x: aload_0
- x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
- x: areturn
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations;
}
SourceFile: "TinyFrameworkClassWideAnnotations.java"
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.class
Compiled from "TinyFrameworkClassWithInitializerDefault.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault
@@ -885,14 +731,14 @@
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static java.lang.Object sObject;
descriptor: Ljava/lang/Object;
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault();
descriptor: ()V
@@ -924,7 +770,7 @@
SourceFile: "TinyFrameworkClassWithInitializerDefault.java"
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.class
Compiled from "TinyFrameworkClassWithInitializerStub.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub
@@ -939,14 +785,14 @@
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static java.lang.Object sObject;
descriptor: Ljava/lang/Object;
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub();
descriptor: ()V
@@ -982,7 +828,7 @@
value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
)
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
x: #x()
android.hosttest.annotation.HostSideTestStaticInitializerKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.class
@@ -999,21 +845,21 @@
flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex GREEN;
descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex BLUE;
descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
private final java.lang.String mLongName;
descriptor: Ljava/lang/String;
@@ -1093,7 +939,7 @@
Signature: #x // (Ljava/lang/String;Ljava/lang/String;)V
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public java.lang.String getLongName();
descriptor: ()Ljava/lang/String;
@@ -1109,7 +955,7 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public java.lang.String getShortName();
descriptor: ()Ljava/lang/String;
@@ -1125,7 +971,7 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $values();
descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
@@ -1187,7 +1033,7 @@
SourceFile: "TinyFrameworkEnumComplex.java"
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.class
Compiled from "TinyFrameworkEnumSimple.java"
public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple>
@@ -1202,14 +1048,14 @@
flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple DOG;
descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $VALUES;
descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
@@ -1308,7 +1154,7 @@
SourceFile: "TinyFrameworkEnumSimple.java"
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
Compiled from "TinyFrameworkExceptionTester.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
@@ -1362,7 +1208,7 @@
SourceFile: "TinyFrameworkExceptionTester.java"
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
Compiled from "TinyFrameworkForTextPolicy.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
@@ -1371,15 +1217,11 @@
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
super_class: #x // java/lang/Object
- interfaces: 0, fields: 3, methods: 19, attributes: 1
+ interfaces: 0, fields: 2, methods: 17, attributes: 1
public int stub;
descriptor: I
flags: (0x0001) ACC_PUBLIC
- public int keep;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
-
public int remove;
descriptor: I
flags: (0x0001) ACC_PUBLIC
@@ -1394,35 +1236,17 @@
x: aload_0
x: iconst_1
x: putfield #x // Field stub:I
- x: aload_0
- x: iconst_2
- x: putfield #x // Field keep:I
- x: return
+ x: return
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
public int addOne(int);
descriptor: (I)I
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
- x: aload_0
- x: iload_1
- x: invokevirtual #x // Method addOneInner:(I)I
- x: ireturn
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
- 0 6 1 value I
-
- public int addOneInner(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=2, locals=2, args_size=2
x: iload_1
x: iconst_1
x: iadd
@@ -1634,19 +1458,6 @@
LocalVariableTable:
Start Length Slot Name Signature
0 3 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
-
- public java.lang.String visibleButUsesUnsupportedMethod();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=1, locals=1, args_size=1
- x: aload_0
- x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
- x: areturn
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
}
SourceFile: "TinyFrameworkForTextPolicy.java"
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.class
@@ -1664,7 +1475,7 @@
Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
descriptor: Ljava/util/function/Supplier;
@@ -1672,7 +1483,7 @@
Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested();
descriptor: ()V
@@ -1691,7 +1502,7 @@
0 14 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested;
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public java.util.function.Supplier<java.lang.Integer> getSupplier();
descriptor: ()Ljava/util/function/Supplier;
@@ -1707,7 +1518,7 @@
Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
descriptor: ()Ljava/util/function/Supplier;
@@ -1720,7 +1531,7 @@
Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
private static java.lang.Integer lambda$getSupplier_static$3();
descriptor: ()Ljava/lang/Integer;
@@ -1775,7 +1586,7 @@
SourceFile: "TinyFrameworkLambdas.java"
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
x: #x()
android.hosttest.annotation.HostSideTestStaticInitializerKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
@@ -1818,7 +1629,7 @@
Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
descriptor: Ljava/util/function/Supplier;
@@ -1826,7 +1637,7 @@
Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas();
descriptor: ()V
@@ -1845,7 +1656,7 @@
0 14 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas;
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public java.util.function.Supplier<java.lang.Integer> getSupplier();
descriptor: ()Ljava/util/function/Supplier;
@@ -1861,7 +1672,7 @@
Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
descriptor: ()Ljava/util/function/Supplier;
@@ -1874,7 +1685,7 @@
Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
private static java.lang.Integer lambda$getSupplier_static$3();
descriptor: ()Ljava/lang/Integer;
@@ -1929,7 +1740,7 @@
SourceFile: "TinyFrameworkLambdas.java"
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
x: #x()
android.hosttest.annotation.HostSideTestStaticInitializerKeep
NestMembers:
@@ -2114,7 +1925,7 @@
SourceFile: "TinyFrameworkMethodCallReplace.java"
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
NestMembers:
com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
BootstrapMethods:
@@ -2134,7 +1945,7 @@
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 11, attributes: 2
+ interfaces: 0, fields: 1, methods: 14, attributes: 2
int value;
descriptor: I
flags: (0x0000)
@@ -2155,6 +1966,9 @@
public static native int nativeAddTwo(int);
descriptor: (I)I
flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+ RuntimeInvisibleAnnotations:
+ x: #x()
+ android.hosttest.annotation.HostSideTestRedirect
public static int nativeAddTwo_should_be_like_this(int);
descriptor: (I)I
@@ -2172,6 +1986,9 @@
public static native long nativeLongPlus(long, long);
descriptor: (JJ)J
flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+ RuntimeInvisibleAnnotations:
+ x: #x()
+ android.hosttest.annotation.HostSideTestRedirect
public static long nativeLongPlus_should_be_like_this(long, long);
descriptor: (JJ)J
@@ -2206,6 +2023,9 @@
public native int nativeNonStaticAddToValue(int);
descriptor: (I)I
flags: (0x0101) ACC_PUBLIC, ACC_NATIVE
+ RuntimeInvisibleAnnotations:
+ x: #x()
+ android.hosttest.annotation.HostSideTestRedirect
public int nativeNonStaticAddToValue_should_be_like_this(int);
descriptor: (I)I
@@ -2229,6 +2049,10 @@
x: #x()
android.hosttest.annotation.HostSideTestThrow
+ public static native void nativeStillKeep();
+ descriptor: ()V
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+
public static void nativeStillNotSupported_should_be_like_this();
descriptor: ()V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
@@ -2243,13 +2067,47 @@
public static native byte nativeBytePlus(byte, byte);
descriptor: (BB)B
flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+ RuntimeInvisibleAnnotations:
+ x: #x()
+ android.hosttest.annotation.HostSideTestRedirect
+
+ public void notNativeRedirected();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=2, locals=1, args_size=1
+ x: new #x // class java/lang/RuntimeException
+ x: dup
+ x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V
+ x: athrow
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 8 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
+ RuntimeInvisibleAnnotations:
+ x: #x()
+ android.hosttest.annotation.HostSideTestRedirect
+
+ public static void notNativeStaticRedirected();
+ descriptor: ()V
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: new #x // class java/lang/RuntimeException
+ x: dup
+ x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V
+ x: athrow
+ LineNumberTable:
+ RuntimeInvisibleAnnotations:
+ x: #x()
+ android.hosttest.annotation.HostSideTestRedirect
}
SourceFile: "TinyFrameworkNative.java"
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
x: #x(#x=s#x)
- android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
+ android.hosttest.annotation.HostSideTestRedirectionClass(
value="TinyFrameworkNative_host"
)
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.class
@@ -2260,7 +2118,7 @@
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 5, attributes: 2
+ interfaces: 0, fields: 0, methods: 7, attributes: 2
public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
@@ -2334,6 +2192,25 @@
Start Length Slot Name Signature
0 5 0 arg1 B
0 5 1 arg2 B
+
+ public static void notNativeRedirected(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;)V
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=0, locals=1, args_size=1
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 1 0 source Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
+
+ public static void notNativeStaticRedirected();
+ descriptor: ()V
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=0, locals=0, args_size=0
+ x: return
+ LineNumberTable:
}
SourceFile: "TinyFrameworkNative_host.java"
RuntimeInvisibleAnnotations:
@@ -2901,7 +2778,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
NestMembers:
com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
@@ -2965,7 +2842,7 @@
SourceFile: "TinyFrameworkPackageRedirect.java"
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.class
Compiled from "TinyFrameworkRenamedClassCaller.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller
@@ -3007,7 +2884,7 @@
SourceFile: "TinyFrameworkRenamedClassCaller.java"
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.class
Compiled from "TinyFrameworkToBeRenamed.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed
@@ -3054,7 +2931,7 @@
SourceFile: "TinyFrameworkToBeRenamed.java"
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
## Class: com/android/hoststubgen/test/tinyframework/packagetest/A.class
Compiled from "A.java"
public class com.android.hoststubgen.test.tinyframework.packagetest.A
@@ -3800,4 +3677,4 @@
SourceFile: "UnsupportedClass.java"
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
deleted file mode 100644
index 86a9c65..0000000
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/02-hoststubgen-test-tiny-framework-host-stub-dump.txt
+++ /dev/null
@@ -1,2788 +0,0 @@
-## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy.class
- Compiled from "IPretendingAidl.java"
-public class com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub$Proxy
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 2, attributes: 4
- public com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub$Proxy();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int addTwo(int);
- descriptor: (I)I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
- public static #x= #x of #x; // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
-SourceFile: "IPretendingAidl.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl
-## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub.class
- Compiled from "IPretendingAidl.java"
-public class com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 2, attributes: 4
- public com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int addOne(int);
- descriptor: (I)I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
- public static #x= #x of #x; // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
-SourceFile: "IPretendingAidl.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl
-## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl.class
- Compiled from "IPretendingAidl.java"
-public interface com.android.hoststubgen.test.tinyframework.IPretendingAidl
- minor version: 0
- major version: 61
- flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
- this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 0, attributes: 4
-}
-InnerClasses:
- public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
- public static #x= #x of #x; // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
-SourceFile: "IPretendingAidl.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestMembers:
- com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
- com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy
-## Class: com/android/hoststubgen/test/tinyframework/R$Nested.class
- Compiled from "R.java"
-public class com.android.hoststubgen.test.tinyframework.R$Nested
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/R$Nested
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 2, attributes: 4
- public static int[] ARRAY;
- descriptor: [I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public com.android.hoststubgen.test.tinyframework.R$Nested();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- static {};
- descriptor: ()V
- flags: (0x0008) ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
-SourceFile: "R.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/R
-## Class: com/android/hoststubgen/test/tinyframework/R.class
- Compiled from "R.java"
-public class com.android.hoststubgen.test.tinyframework.R
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/R
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 1, attributes: 4
- public com.android.hoststubgen.test.tinyframework.R();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
-SourceFile: "R.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestMembers:
- com/android/hoststubgen/test/tinyframework/R$Nested
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.class
- Compiled from "TinyFrameworkAnnotations.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 5, attributes: 3
- public int stub;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public int addOne(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public int addTwo(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int nativeAddThree(int);
- descriptor: (I)I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public java.lang.String visibleButUsesUnsupportedMethod();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-}
-SourceFile: "TinyFrameworkAnnotations.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
- x: #x(#x=s#x)
- android.hosttest.annotation.HostSideTestClassLoadHook(
- value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
- )
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
- Compiled from "TinyFrameworkCallerCheck.java"
-class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
- minor version: 0
- major version: 61
- flags: (0x0020) ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 2, attributes: 4
- private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
- descriptor: ()V
- flags: (0x0002) ACC_PRIVATE
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int getOneStub();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-}
-InnerClasses:
- private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-SourceFile: "TinyFrameworkCallerCheck.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
- Compiled from "TinyFrameworkCallerCheck.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 3, attributes: 5
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int getOne_withCheck();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int getOne_noCheck();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-SourceFile: "TinyFrameworkCallerCheck.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-NestMembers:
- com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
- Compiled from "TinyFrameworkClassLoadHook.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 3, attributes: 3
- public static final java.util.Set<java.lang.Class<?>> sLoadedClasses;
- descriptor: Ljava/util/Set;
- flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
- Signature: #x // Ljava/util/Set<Ljava/lang/Class<*>;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook();
- descriptor: ()V
- flags: (0x0002) ACC_PRIVATE
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static void onClassLoaded(java.lang.Class<?>);
- descriptor: (Ljava/lang/Class;)V
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // (Ljava/lang/Class<*>;)V
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- static {};
- descriptor: ()V
- flags: (0x0008) ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkClassLoadHook.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.class
- Compiled from "TinyFrameworkClassWideAnnotations.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 4, attributes: 3
- public int stub;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int addOne(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int addTwo(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public java.lang.String visibleButUsesUnsupportedMethod();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkClassWideAnnotations.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.class
- Compiled from "TinyFrameworkClassWithInitializerDefault.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 2, methods: 0, attributes: 3
- public static boolean sInitialized;
- descriptor: Z
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public static java.lang.Object sObject;
- descriptor: Ljava/lang/Object;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
-}
-SourceFile: "TinyFrameworkClassWithInitializerDefault.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.class
- Compiled from "TinyFrameworkClassWithInitializerStub.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 2, methods: 0, attributes: 3
- public static boolean sInitialized;
- descriptor: Z
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public static java.lang.Object sObject;
- descriptor: Ljava/lang/Object;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
-}
-SourceFile: "TinyFrameworkClassWithInitializerStub.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x(#x=s#x)
- android.hosttest.annotation.HostSideTestClassLoadHook(
- value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
- )
- x: #x()
- android.hosttest.annotation.HostSideTestStub
- x: #x()
- android.hosttest.annotation.HostSideTestStaticInitializerKeep
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.class
- Compiled from "TinyFrameworkEnumComplex.java"
-public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex>
- minor version: 0
- major version: 61
- flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex
- super_class: #x // java/lang/Enum
- interfaces: 0, fields: 4, methods: 7, attributes: 4
- public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex RED;
- descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
- flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex GREEN;
- descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
- flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex BLUE;
- descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
- flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $VALUES;
- descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
- flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] values();
- descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex valueOf(java.lang.String);
- descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- MethodParameters:
- Name Flags
- <no name> mandated
-
- private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String);
- descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
- flags: (0x0002) ACC_PRIVATE
- Code:
- stack=3, locals=5, args_size=5
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // (Ljava/lang/String;Ljava/lang/String;)V
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
- MethodParameters:
- Name Flags
- <no name> synthetic
- <no name> synthetic
- <no name>
- <no name>
-
- public java.lang.String getLongName();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public java.lang.String getShortName();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $values();
- descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- static {};
- descriptor: ()V
- flags: (0x0008) ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;>;
-SourceFile: "TinyFrameworkEnumComplex.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.class
- Compiled from "TinyFrameworkEnumSimple.java"
-public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple>
- minor version: 0
- major version: 61
- flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple
- super_class: #x // java/lang/Enum
- interfaces: 0, fields: 3, methods: 5, attributes: 4
- public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple CAT;
- descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
- flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple DOG;
- descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
- flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $VALUES;
- descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
- flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] values();
- descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple valueOf(java.lang.String);
- descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- MethodParameters:
- Name Flags
- <no name> mandated
-
- private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple();
- descriptor: (Ljava/lang/String;I)V
- flags: (0x0002) ACC_PRIVATE
- Code:
- stack=3, locals=3, args_size=3
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // ()V
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- MethodParameters:
- Name Flags
- <no name> synthetic
- <no name> synthetic
-
- private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values();
- descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- static {};
- descriptor: ()V
- flags: (0x0008) ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;>;
-SourceFile: "TinyFrameworkEnumSimple.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
- Compiled from "TinyFrameworkExceptionTester.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 2, attributes: 3
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int testException();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkExceptionTester.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
- Compiled from "TinyFrameworkForTextPolicy.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 14, attributes: 2
- public int stub;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int addOne(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public java.lang.String toBeIgnoredObj();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public void toBeIgnoredV();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public boolean toBeIgnoredZ();
- descriptor: ()Z
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public byte toBeIgnoredB();
- descriptor: ()B
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public char toBeIgnoredC();
- descriptor: ()C
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public short toBeIgnoredS();
- descriptor: ()S
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int toBeIgnoredI();
- descriptor: ()I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public float toBeIgnoredF();
- descriptor: ()F
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public double toBeIgnoredD();
- descriptor: ()D
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int addTwo(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int nativeAddThree(int);
- descriptor: (I)I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public java.lang.String visibleButUsesUnsupportedMethod();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkForTextPolicy.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.class
- Compiled from "TinyFrameworkLambdas.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 2, methods: 7, attributes: 5
- public final java.util.function.Supplier<java.lang.Integer> mSupplier;
- descriptor: Ljava/util/function/Supplier;
- flags: (0x0011) ACC_PUBLIC, ACC_FINAL
- Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
- descriptor: Ljava/util/function/Supplier;
- flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
- Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public java.util.function.Supplier<java.lang.Integer> getSupplier();
- descriptor: ()Ljava/util/function/Supplier;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
- descriptor: ()Ljava/util/function/Supplier;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- private static java.lang.Integer lambda$getSupplier_static$3();
- descriptor: ()Ljava/lang/Integer;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- private static java.lang.Integer lambda$getSupplier$2();
- descriptor: ()Ljava/lang/Integer;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- private static java.lang.Integer lambda$static$1();
- descriptor: ()Ljava/lang/Integer;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- private static java.lang.Integer lambda$new$0();
- descriptor: ()Ljava/lang/Integer;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
- public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
-SourceFile: "TinyFrameworkLambdas.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
- x: #x()
- android.hosttest.annotation.HostSideTestStaticInitializerKeep
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.class
- Compiled from "TinyFrameworkLambdas.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 2, methods: 7, attributes: 5
- public final java.util.function.Supplier<java.lang.Integer> mSupplier;
- descriptor: Ljava/util/function/Supplier;
- flags: (0x0011) ACC_PUBLIC, ACC_FINAL
- Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
- descriptor: Ljava/util/function/Supplier;
- flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
- Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public java.util.function.Supplier<java.lang.Integer> getSupplier();
- descriptor: ()Ljava/util/function/Supplier;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
- descriptor: ()Ljava/util/function/Supplier;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- private static java.lang.Integer lambda$getSupplier_static$3();
- descriptor: ()Ljava/lang/Integer;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- private static java.lang.Integer lambda$getSupplier$2();
- descriptor: ()Ljava/lang/Integer;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- private static java.lang.Integer lambda$static$1();
- descriptor: ()Ljava/lang/Integer;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- private static java.lang.Integer lambda$new$0();
- descriptor: ()Ljava/lang/Integer;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
- public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
-SourceFile: "TinyFrameworkLambdas.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
- x: #x()
- android.hosttest.annotation.HostSideTestStaticInitializerKeep
-NestMembers:
- com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class
- Compiled from "TinyFrameworkMethodCallReplace.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 3, attributes: 4
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static void startThread(java.lang.Thread);
- descriptor: (Ljava/lang/Thread;)V
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int add(int, int);
- descriptor: (II)I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
-SourceFile: "TinyFrameworkMethodCallReplace.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class
- Compiled from "TinyFrameworkMethodCallReplace.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 4, attributes: 5
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static boolean nonStaticMethodCallReplaceTester() throws java.lang.Exception;
- descriptor: ()Z
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Exceptions:
- throws java.lang.Exception
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int staticMethodCallReplaceTester();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean);
- descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
- public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
-SourceFile: "TinyFrameworkMethodCallReplace.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-NestMembers:
- com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
- Compiled from "TinyFrameworkNative.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 10, attributes: 3
- int value;
- descriptor: I
- flags: (0x0000)
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static native int nativeAddTwo(int);
- descriptor: (I)I
- flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int nativeAddTwo_should_be_like_this(int);
- descriptor: (I)I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static native long nativeLongPlus(long, long);
- descriptor: (JJ)J
- flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static long nativeLongPlus_should_be_like_this(long, long);
- descriptor: (JJ)J
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=4, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public void setValue(int);
- descriptor: (I)V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public native int nativeNonStaticAddToValue(int);
- descriptor: (I)I
- flags: (0x0101) ACC_PUBLIC, ACC_NATIVE
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int nativeNonStaticAddToValue_should_be_like_this(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static void nativeStillNotSupported_should_be_like_this();
- descriptor: ()V
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static native byte nativeBytePlus(byte, byte);
- descriptor: (BB)B
- flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkNative.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
- x: #x(#x=s#x)
- android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
- value="TinyFrameworkNative_host"
- )
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
- Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 1, attributes: 4
- public int value;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int);
- descriptor: (I)V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class
- Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 2, methods: 1, attributes: 4
- public int value;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
- descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
- flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
- descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- MethodParameters:
- Name Flags
- <no name> final mandated
-}
-InnerClasses:
- public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass.class
- Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 1, attributes: 4
- public int value;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
- public static #x= #x of #x; // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class
- Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 2, attributes: 4
- public int value;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
- descriptor: ()Ljava/util/function/Supplier;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
- #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
- public static #x= #x of #x; // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class
- Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass extends com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
- super_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
- interfaces: 0, fields: 0, methods: 1, attributes: 4
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int);
- descriptor: (I)V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
- public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class
- Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 2, methods: 4, attributes: 5
- public final java.util.function.Supplier<java.lang.Integer> mSupplier;
- descriptor: Ljava/util/function/Supplier;
- flags: (0x0011) ACC_PUBLIC, ACC_FINAL
- Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
- descriptor: Ljava/util/function/Supplier;
- flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
- Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public java.util.function.Supplier<java.lang.Integer> getSupplier();
- descriptor: ()Ljava/util/function/Supplier;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
- descriptor: ()Ljava/util/function/Supplier;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- static {};
- descriptor: ()V
- flags: (0x0008) ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
- #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
- #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
- #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
- public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
- public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
- public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
- public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
- public static #x= #x of #x; // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
- #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-NestMembers:
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.class
- Compiled from "TinyFrameworkPackageRedirect.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 2, attributes: 3
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int foo(int);
- descriptor: (I)I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkPackageRedirect.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.class
- Compiled from "TinyFrameworkRenamedClassCaller.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 2, attributes: 3
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int foo(int);
- descriptor: (I)I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkRenamedClassCaller.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/packagetest/A.class
- Compiled from "A.java"
-public class com.android.hoststubgen.test.tinyframework.packagetest.A
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/A
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "A.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/packagetest/sub/A.class
- Compiled from "A.java"
-public class com.android.hoststubgen.test.tinyframework.packagetest.sub.A
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/sub/A
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "A.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C1.class
- Compiled from "C1.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.C1
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "C1.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C2.class
- Compiled from "C2.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2
- super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "C2.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C3.class
- Compiled from "C3.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3
- super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "C3.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CA.class
- Compiled from "CA.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.CA
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CA
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "CA.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CB.class
- Compiled from "CB.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.CB
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "CB.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I1.class
- Compiled from "I1.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.I1
- minor version: 0
- major version: 61
- flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I1
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "I1.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I2.class
- Compiled from "I2.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.I2 extends com.android.hoststubgen.test.tinyframework.subclasstest.I1
- minor version: 0
- major version: 61
- flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I2
- super_class: #x // java/lang/Object
- interfaces: 1, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "I2.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I3.class
- Compiled from "I3.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.I3 extends com.android.hoststubgen.test.tinyframework.subclasstest.I2
- minor version: 0
- major version: 61
- flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I3
- super_class: #x // java/lang/Object
- interfaces: 1, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "I3.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IA.class
- Compiled from "IA.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.IA
- minor version: 0
- major version: 61
- flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IA
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "IA.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IB.class
- Compiled from "IB.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.IB
- minor version: 0
- major version: 61
- flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IB
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "IB.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/unsupported/UnsupportedClass.class
- Compiled from "UnsupportedClass.java"
-public class com.unsupported.UnsupportedClass
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/unsupported/UnsupportedClass
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 2, attributes: 3
- public com.unsupported.UnsupportedClass(int);
- descriptor: (I)V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int getValue();
- descriptor: ()I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "UnsupportedClass.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.class
- Compiled from "TinyFrameworkToBeRenamed.java"
-public class rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 2, attributes: 3
- private final int mValue;
- descriptor: I
- flags: (0x0012) ACC_PRIVATE, ACC_FINAL
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed(int);
- descriptor: (I)V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int getValue();
- descriptor: ()I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkToBeRenamed.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt
similarity index 68%
rename from tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
rename to tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt
index c6b9c7a..31bbcc5 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-impl-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/03-hoststubgen-test-tiny-framework-host-dump.txt
@@ -12,12 +12,12 @@
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "HostSideTestClassLoadHook.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -39,7 +39,7 @@
SourceFile: "HostSideTestKeep.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
@@ -48,13 +48,35 @@
java.lang.annotation.Retention(
value=Ljava/lang/annotation/RetentionPolicy;.CLASS
)
-## Class: android/hosttest/annotation/HostSideTestNativeSubstitutionClass.class
- Compiled from "HostSideTestNativeSubstitutionClass.java"
-public interface android.hosttest.annotation.HostSideTestNativeSubstitutionClass extends java.lang.annotation.Annotation
+## Class: android/hosttest/annotation/HostSideTestRedirect.class
+ Compiled from "HostSideTestRedirect.java"
+public interface android.hosttest.annotation.HostSideTestRedirect extends java.lang.annotation.Annotation
minor version: 0
major version: 61
flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
- this_class: #x // android/hosttest/annotation/HostSideTestNativeSubstitutionClass
+ this_class: #x // android/hosttest/annotation/HostSideTestRedirect
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+}
+SourceFile: "HostSideTestRedirect.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+ x: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.METHOD]
+ )
+ x: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestRedirectionClass.class
+ Compiled from "HostSideTestRedirectionClass.java"
+public interface android.hosttest.annotation.HostSideTestRedirectionClass extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestRedirectionClass
super_class: #x // java/lang/Object
interfaces: 1, fields: 0, methods: 1, attributes: 2
public abstract java.lang.String value();
@@ -62,12 +84,12 @@
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
-SourceFile: "HostSideTestNativeSubstitutionClass.java"
+SourceFile: "HostSideTestRedirectionClass.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -89,7 +111,7 @@
SourceFile: "HostSideTestRemove.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
@@ -98,20 +120,20 @@
java.lang.annotation.Retention(
value=Ljava/lang/annotation/RetentionPolicy;.CLASS
)
-## Class: android/hosttest/annotation/HostSideTestStub.class
- Compiled from "HostSideTestStub.java"
-public interface android.hosttest.annotation.HostSideTestStub extends java.lang.annotation.Annotation
+## Class: android/hosttest/annotation/HostSideTestStaticInitializerKeep.class
+ Compiled from "HostSideTestStaticInitializerKeep.java"
+public interface android.hosttest.annotation.HostSideTestStaticInitializerKeep extends java.lang.annotation.Annotation
minor version: 0
major version: 61
flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
- this_class: #x // android/hosttest/annotation/HostSideTestStub
+ this_class: #x // android/hosttest/annotation/HostSideTestStaticInitializerKeep
super_class: #x // java/lang/Object
interfaces: 1, fields: 0, methods: 0, attributes: 2
}
-SourceFile: "HostSideTestStub.java"
+SourceFile: "HostSideTestStaticInitializerKeep.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
@@ -134,12 +156,12 @@
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "HostSideTestSubstitute.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.METHOD]
@@ -161,7 +183,7 @@
SourceFile: "HostSideTestThrow.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
x: #x(#x=[e#x.#x,e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
@@ -183,29 +205,7 @@
SourceFile: "HostSideTestWholeClassKeep.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- x: #x(#x=[e#x.#x])
- java.lang.annotation.Target(
- value=[Ljava/lang/annotation/ElementType;.TYPE]
- )
- x: #x(#x=e#x.#x)
- java.lang.annotation.Retention(
- value=Ljava/lang/annotation/RetentionPolicy;.CLASS
- )
-## Class: android/hosttest/annotation/HostSideTestWholeClassStub.class
- Compiled from "HostSideTestWholeClassStub.java"
-public interface android.hosttest.annotation.HostSideTestWholeClassStub extends java.lang.annotation.Annotation
- minor version: 0
- major version: 61
- flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
- this_class: #x // android/hosttest/annotation/HostSideTestWholeClassStub
- super_class: #x // java/lang/Object
- interfaces: 1, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "HostSideTestWholeClassStub.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -237,9 +237,7 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int addTwo(int);
descriptor: (I)I
@@ -256,9 +254,7 @@
0 4 0 a I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
@@ -266,9 +262,7 @@
SourceFile: "IPretendingAidl.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl
## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub.class
Compiled from "IPretendingAidl.java"
@@ -293,9 +287,7 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int addOne(int);
descriptor: (I)I
@@ -312,19 +304,15 @@
0 4 0 a I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
- public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
+ public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
public static #x= #x of #x; // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
SourceFile: "IPretendingAidl.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl
## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl.class
Compiled from "IPretendingAidl.java"
@@ -342,9 +330,7 @@
SourceFile: "IPretendingAidl.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestMembers:
com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy
@@ -362,9 +348,7 @@
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public com.android.hoststubgen.test.tinyframework.R$Nested();
descriptor: ()V
@@ -380,9 +364,7 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/R$Nested;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
static {};
descriptor: ()V
@@ -400,18 +382,14 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
- public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
+ public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
SourceFile: "R.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/R
## Class: com/android/hoststubgen/test/tinyframework/R.class
Compiled from "R.java"
@@ -436,18 +414,14 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/R;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
- public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
+ public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
SourceFile: "R.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestMembers:
com/android/hoststubgen/test/tinyframework/R$Nested
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.class
@@ -458,25 +432,13 @@
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
super_class: #x // java/lang/Object
- interfaces: 0, fields: 2, methods: 8, attributes: 3
- public int stub;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
+ interfaces: 0, fields: 1, methods: 6, attributes: 3
public int keep;
descriptor: I
flags: (0x0001) ACC_PUBLIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestKeep
@@ -487,7 +449,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
- x: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
+ x: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -500,70 +462,36 @@
x: invokespecial #x // Method java/lang/Object."<init>":()V
x: aload_0
x: iconst_1
- x: putfield #x // Field stub:I
- x: aload_0
- x: iconst_2
- x: putfield #x // Field keep:I
- x: return
+ x: putfield #x // Field keep:I
+ x: return
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public int addOne(int);
descriptor: (I)I
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
- x: aload_0
x: iload_1
- x: invokevirtual #x // Method addOneInner:(I)I
+ x: iconst_1
+ x: iadd
x: ireturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
- 0 6 1 value I
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
+ 0 4 1 value I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public int addOneInner(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=4, locals=2, args_size=2
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
- x: ldc #x // String addOneInner
- x: ldc #x // String (I)I
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: iload_1
- x: iconst_1
- x: iadd
- x: ireturn
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 15 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
- 15 4 1 value I
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestKeep
@@ -586,9 +514,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int nativeAddThree(int);
descriptor: (I)I
@@ -607,212 +533,39 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.String unsupportedMethod();
descriptor: ()Ljava/lang/String;
flags: (0x0001) ACC_PUBLIC
Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
- x: ldc #x // String unsupportedMethod
- x: ldc #x // String ()Ljava/lang/String;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Unreachable
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ stack=3, locals=1, args_size=1
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
+ x: new #x // class java/lang/RuntimeException
+ x: dup
+ x: ldc #x // String Unreachable
+ x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
x: athrow
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestThrow
-
- public java.lang.String visibleButUsesUnsupportedMethod();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=1, locals=1, args_size=1
- x: aload_0
- x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
- x: areturn
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
}
SourceFile: "TinyFrameworkAnnotations.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
x: #x(#x=s#x)
android.hosttest.annotation.HostSideTestClassLoadHook(
value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
)
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
- Compiled from "TinyFrameworkCallerCheck.java"
-class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
- minor version: 0
- major version: 61
- flags: (0x0020) ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 3, attributes: 4
- private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
- descriptor: ()V
- flags: (0x0002) ACC_PRIVATE
- Code:
- stack=1, locals=1, args_size=1
- x: aload_0
- x: invokespecial #x // Method java/lang/Object."<init>":()V
- x: return
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int getOneKeep();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=4, locals=0, args_size=0
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
- x: ldc #x // String getOneKeep
- x: ldc #x // String ()I
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: iconst_1
- x: ireturn
- LineNumberTable:
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestKeep
-
- public static int getOneStub();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=1, locals=0, args_size=0
- x: iconst_1
- x: ireturn
- LineNumberTable:
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-}
-InnerClasses:
- private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-SourceFile: "TinyFrameworkCallerCheck.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
- Compiled from "TinyFrameworkCallerCheck.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 3, attributes: 5
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=1, locals=1, args_size=1
- x: aload_0
- x: invokespecial #x // Method java/lang/Object."<init>":()V
- x: return
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int getOne_withCheck();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=1, locals=0, args_size=0
- x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneKeep:()I
- x: ireturn
- LineNumberTable:
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int getOne_noCheck();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=1, locals=0, args_size=0
- x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneStub:()I
- x: ireturn
- LineNumberTable:
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-SourceFile: "TinyFrameworkCallerCheck.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-NestMembers:
- com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
Compiled from "TinyFrameworkClassLoadHook.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
@@ -828,9 +581,7 @@
Signature: #x // Ljava/util/Set<Ljava/lang/Class<*>;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook();
descriptor: ()V
@@ -846,9 +597,7 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static void onClassLoaded(java.lang.Class<?>);
descriptor: (Ljava/lang/Class;)V
@@ -870,9 +619,7 @@
Signature: #x // (Ljava/lang/Class<*>;)V
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
static {};
descriptor: ()V
@@ -887,19 +634,15 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkClassLoadHook.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.class
Compiled from "TinyFrameworkClassWideAnnotations.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations
@@ -908,15 +651,13 @@
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations
super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 5, attributes: 3
- public int stub;
+ interfaces: 0, fields: 1, methods: 4, attributes: 3
+ public int keep;
descriptor: I
flags: (0x0001) ACC_PUBLIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations();
descriptor: ()V
@@ -927,7 +668,7 @@
x: invokespecial #x // Method java/lang/Object."<init>":()V
x: aload_0
x: iconst_1
- x: putfield #x // Field stub:I
+ x: putfield #x // Field keep:I
x: return
LineNumberTable:
LocalVariableTable:
@@ -935,9 +676,7 @@
0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public int addOne(int);
descriptor: (I)I
@@ -955,9 +694,7 @@
0 4 1 value I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public int addTwo(int);
descriptor: (I)I
@@ -977,63 +714,35 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.String unsupportedMethod();
descriptor: ()Ljava/lang/String;
flags: (0x0001) ACC_PUBLIC
Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations
- x: ldc #x // String unsupportedMethod
- x: ldc #x // String ()Ljava/lang/String;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Unreachable
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ stack=3, locals=1, args_size=1
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
+ x: new #x // class java/lang/RuntimeException
+ x: dup
+ x: ldc #x // String Unreachable
+ x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
x: athrow
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestThrow
-
- public java.lang.String visibleButUsesUnsupportedMethod();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=1, locals=1, args_size=1
- x: aload_0
- x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
- x: areturn
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
SourceFile: "TinyFrameworkClassWideAnnotations.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.class
Compiled from "TinyFrameworkClassWithInitializerDefault.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault
@@ -1048,35 +757,29 @@
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static java.lang.Object sObject;
descriptor: Ljava/lang/Object;
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
}
SourceFile: "TinyFrameworkClassWithInitializerDefault.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.class
Compiled from "TinyFrameworkClassWithInitializerStub.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub
@@ -1091,24 +794,20 @@
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static java.lang.Object sObject;
descriptor: Ljava/lang/Object;
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
static {};
descriptor: ()V
@@ -1128,21 +827,19 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkClassWithInitializerStub.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x(#x=s#x)
android.hosttest.annotation.HostSideTestClassLoadHook(
value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
)
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
x: #x()
android.hosttest.annotation.HostSideTestStaticInitializerKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.class
@@ -1159,43 +856,37 @@
flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex GREEN;
descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex BLUE;
descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
private final java.lang.String mLongName;
descriptor: Ljava/lang/String;
flags: (0x0012) ACC_PRIVATE, ACC_FINAL
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestKeep
@@ -1205,7 +896,7 @@
flags: (0x0012) ACC_PRIVATE, ACC_FINAL
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestKeep
@@ -1215,9 +906,7 @@
flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] values();
descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
@@ -1231,9 +920,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex valueOf(java.lang.String);
descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
@@ -1251,9 +938,7 @@
0 10 0 name Ljava/lang/String;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
MethodParameters:
Name Flags
<no name> mandated
@@ -1283,12 +968,10 @@
Signature: #x // (Ljava/lang/String;Ljava/lang/String;)V
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
MethodParameters:
Name Flags
<no name> synthetic
@@ -1310,12 +993,10 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public java.lang.String getShortName();
descriptor: ()Ljava/lang/String;
@@ -1331,12 +1012,10 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $values();
descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
@@ -1361,9 +1040,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
static {};
descriptor: ()V
@@ -1400,20 +1077,16 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;>;
SourceFile: "TinyFrameworkEnumComplex.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.class
Compiled from "TinyFrameworkEnumSimple.java"
public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple>
@@ -1428,33 +1101,27 @@
flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple DOG;
descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $VALUES;
descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] values();
descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
@@ -1468,9 +1135,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple valueOf(java.lang.String);
descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
@@ -1488,9 +1153,7 @@
0 10 0 name Ljava/lang/String;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
MethodParameters:
Name Flags
<no name> mandated
@@ -1512,9 +1175,7 @@
Signature: #x // ()V
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
MethodParameters:
Name Flags
<no name> synthetic
@@ -1539,9 +1200,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
static {};
descriptor: ()V
@@ -1566,20 +1225,16 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;>;
SourceFile: "TinyFrameworkEnumSimple.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
Compiled from "TinyFrameworkExceptionTester.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
@@ -1603,9 +1258,7 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int testException();
descriptor: ()I
@@ -1636,19 +1289,15 @@
11 11 0 e Ljava/lang/Exception;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkExceptionTester.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
Compiled from "TinyFrameworkForTextPolicy.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
@@ -1657,22 +1306,13 @@
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
super_class: #x // java/lang/Object
- interfaces: 0, fields: 2, methods: 17, attributes: 2
+ interfaces: 0, fields: 1, methods: 15, attributes: 2
public int stub;
descriptor: I
flags: (0x0001) ACC_PUBLIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int keep;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static {};
descriptor: ()V
@@ -1680,7 +1320,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
- x: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
+ x: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -1694,63 +1334,32 @@
x: aload_0
x: iconst_1
x: putfield #x // Field stub:I
- x: aload_0
- x: iconst_2
- x: putfield #x // Field keep:I
- x: return
+ x: return
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 0 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public int addOne(int);
descriptor: (I)I
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
- x: aload_0
x: iload_1
- x: invokevirtual #x // Method addOneInner:(I)I
+ x: iconst_1
+ x: iadd
x: ireturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
- 0 6 1 value I
+ 0 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 0 4 1 value I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int addOneInner(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=4, locals=2, args_size=2
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
- x: ldc #x // String addOneInner
- x: ldc #x // String (I)I
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: iload_1
- x: iconst_1
- x: iadd
- x: ireturn
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 15 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
- 15 4 1 value I
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.String toBeIgnoredObj();
descriptor: ()Ljava/lang/String;
@@ -1763,9 +1372,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public void toBeIgnoredV();
descriptor: ()V
@@ -1777,9 +1384,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public boolean toBeIgnoredZ();
descriptor: ()Z
@@ -1792,9 +1397,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public byte toBeIgnoredB();
descriptor: ()B
@@ -1807,9 +1410,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public char toBeIgnoredC();
descriptor: ()C
@@ -1822,9 +1423,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public short toBeIgnoredS();
descriptor: ()S
@@ -1837,9 +1436,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public int toBeIgnoredI();
descriptor: ()I
@@ -1852,9 +1449,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public float toBeIgnoredF();
descriptor: ()F
@@ -1867,9 +1462,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public double toBeIgnoredD();
descriptor: ()D
@@ -1882,9 +1475,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public int addTwo(int);
descriptor: (I)I
@@ -1904,9 +1495,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int nativeAddThree(int);
descriptor: (I)I
@@ -1925,57 +1514,29 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.String unsupportedMethod();
descriptor: ()Ljava/lang/String;
flags: (0x0001) ACC_PUBLIC
Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
- x: ldc #x // String unsupportedMethod
- x: ldc #x // String ()Ljava/lang/String;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Unreachable
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ stack=3, locals=1, args_size=1
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
+ x: new #x // class java/lang/RuntimeException
+ x: dup
+ x: ldc #x // String Unreachable
+ x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
x: athrow
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public java.lang.String visibleButUsesUnsupportedMethod();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=1, locals=1, args_size=1
- x: aload_0
- x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
- x: areturn
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkForTextPolicy.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.class
Compiled from "TinyFrameworkLambdas.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested
@@ -1991,12 +1552,10 @@
Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
descriptor: Ljava/util/function/Supplier;
@@ -2004,12 +1563,10 @@
Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested();
descriptor: ()V
@@ -2028,12 +1585,10 @@
0 14 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public java.util.function.Supplier<java.lang.Integer> getSupplier();
descriptor: ()Ljava/util/function/Supplier;
@@ -2049,12 +1604,10 @@
Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
descriptor: ()Ljava/util/function/Supplier;
@@ -2067,12 +1620,10 @@
Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
private static java.lang.Integer lambda$getSupplier_static$3();
descriptor: ()Ljava/lang/Integer;
@@ -2085,9 +1636,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static java.lang.Integer lambda$getSupplier$2();
descriptor: ()Ljava/lang/Integer;
@@ -2100,9 +1649,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static java.lang.Integer lambda$static$1();
descriptor: ()Ljava/lang/Integer;
@@ -2115,9 +1662,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static java.lang.Integer lambda$new$0();
descriptor: ()Ljava/lang/Integer;
@@ -2130,9 +1675,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
static {};
descriptor: ()V
@@ -2145,7 +1688,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
@@ -2153,12 +1696,10 @@
SourceFile: "TinyFrameworkLambdas.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
x: #x()
android.hosttest.annotation.HostSideTestStaticInitializerKeep
BootstrapMethods:
@@ -2198,12 +1739,10 @@
Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
descriptor: Ljava/util/function/Supplier;
@@ -2211,12 +1750,10 @@
Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas();
descriptor: ()V
@@ -2235,12 +1772,10 @@
0 14 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public java.util.function.Supplier<java.lang.Integer> getSupplier();
descriptor: ()Ljava/util/function/Supplier;
@@ -2256,12 +1791,10 @@
Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
descriptor: ()Ljava/util/function/Supplier;
@@ -2274,12 +1807,10 @@
Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
private static java.lang.Integer lambda$getSupplier_static$3();
descriptor: ()Ljava/lang/Integer;
@@ -2292,9 +1823,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static java.lang.Integer lambda$getSupplier$2();
descriptor: ()Ljava/lang/Integer;
@@ -2307,9 +1836,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static java.lang.Integer lambda$static$1();
descriptor: ()Ljava/lang/Integer;
@@ -2322,9 +1849,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static java.lang.Integer lambda$new$0();
descriptor: ()Ljava/lang/Integer;
@@ -2337,9 +1862,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
static {};
descriptor: ()V
@@ -2352,7 +1875,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
@@ -2360,12 +1883,10 @@
SourceFile: "TinyFrameworkLambdas.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
x: #x()
android.hosttest.annotation.HostSideTestStaticInitializerKeep
BootstrapMethods:
@@ -2414,9 +1935,7 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static void startThread(java.lang.Thread);
descriptor: (Ljava/lang/Thread;)V
@@ -2435,9 +1954,7 @@
0 10 0 thread Ljava/lang/Thread;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int add(int, int);
descriptor: (II)I
@@ -2455,18 +1972,14 @@
0 4 1 b I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
- public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+ public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
SourceFile: "TinyFrameworkMethodCallReplace.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class
Compiled from "TinyFrameworkMethodCallReplace.java"
@@ -2491,9 +2004,7 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static boolean nonStaticMethodCallReplaceTester() throws java.lang.Exception;
descriptor: ()Z
@@ -2527,9 +2038,7 @@
throws java.lang.Exception
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int staticMethodCallReplaceTester();
descriptor: ()I
@@ -2543,9 +2052,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean);
descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V
@@ -2563,22 +2070,18 @@
0 11 0 ab Ljava/util/concurrent/atomic/AtomicBoolean;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
- public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
+ public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
SourceFile: "TinyFrameworkMethodCallReplace.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
BootstrapMethods:
x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
@@ -2595,15 +2098,13 @@
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 11, attributes: 3
+ interfaces: 0, fields: 1, methods: 14, attributes: 3
int value;
descriptor: I
flags: (0x0000)
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative();
descriptor: ()V
@@ -2619,9 +2120,7 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int nativeAddTwo(int);
descriptor: (I)I
@@ -2635,9 +2134,10 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+ RuntimeInvisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ android.hosttest.annotation.HostSideTestRedirect
public static int nativeAddTwo_should_be_like_this(int);
descriptor: (I)I
@@ -2653,9 +2153,7 @@
0 5 0 arg I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static long nativeLongPlus(long, long);
descriptor: (JJ)J
@@ -2670,9 +2168,10 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+ RuntimeInvisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ android.hosttest.annotation.HostSideTestRedirect
public static long nativeLongPlus_should_be_like_this(long, long);
descriptor: (JJ)J
@@ -2690,9 +2189,7 @@
0 6 2 arg2 J
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public void setValue(int);
descriptor: (I)V
@@ -2710,9 +2207,7 @@
0 6 1 v I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public int nativeNonStaticAddToValue(int);
descriptor: (I)I
@@ -2727,9 +2222,10 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+ RuntimeInvisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ android.hosttest.annotation.HostSideTestRedirect
public int nativeNonStaticAddToValue_should_be_like_this(int);
descriptor: (I)I
@@ -2747,38 +2243,35 @@
0 6 1 arg I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static void nativeStillNotSupported();
descriptor: ()V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
- stack=4, locals=0, args_size=0
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
- x: ldc #x // String nativeStillNotSupported
- x: ldc #x // String ()V
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Unreachable
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ stack=3, locals=0, args_size=0
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
+ x: new #x // class java/lang/RuntimeException
+ x: dup
+ x: ldc #x // String Unreachable
+ x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
x: athrow
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestThrow
+ public static native void nativeStillKeep();
+ descriptor: ()V
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
public static void nativeStillNotSupported_should_be_like_this();
descriptor: ()V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
@@ -2791,9 +2284,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static byte nativeBytePlus(byte, byte);
descriptor: (BB)B
@@ -2808,21 +2299,53 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+ RuntimeInvisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ android.hosttest.annotation.HostSideTestRedirect
+
+ public void notNativeRedirected();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.notNativeRedirected:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;)V
+ x: return
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+ RuntimeInvisibleAnnotations:
+ x: #x()
+ android.hosttest.annotation.HostSideTestRedirect
+
+ public static void notNativeStaticRedirected();
+ descriptor: ()V
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=0, locals=0, args_size=0
+ x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.notNativeStaticRedirected:()V
+ x: return
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+ RuntimeInvisibleAnnotations:
+ x: #x()
+ android.hosttest.annotation.HostSideTestRedirect
}
SourceFile: "TinyFrameworkNative.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
x: #x(#x=s#x)
- android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
+ android.hosttest.annotation.HostSideTestRedirectionClass(
value="TinyFrameworkNative_host"
)
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.class
@@ -2833,130 +2356,125 @@
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 5, attributes: 3
+ interfaces: 0, fields: 0, methods: 7, attributes: 3
public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative_host();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
- x: ldc #x // String <init>
- x: ldc #x // String ()V
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: aload_0
- x: invokespecial #x // Method java/lang/Object."<init>":()V
- x: return
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: return
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host;
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int nativeAddTwo(int);
descriptor: (I)I
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
- x: ldc #x // String nativeAddTwo
- x: ldc #x // String (I)I
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: iload_0
- x: iconst_2
- x: iadd
- x: ireturn
+ stack=2, locals=1, args_size=1
+ x: iload_0
+ x: iconst_2
+ x: iadd
+ x: ireturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 15 4 0 arg I
+ 0 4 0 arg I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static long nativeLongPlus(long, long);
descriptor: (JJ)J
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=4, args_size=2
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
- x: ldc #x // String nativeLongPlus
- x: ldc #x // String (JJ)J
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: lload_0
- x: lload_2
- x: ladd
- x: lreturn
+ x: lload_0
+ x: lload_2
+ x: ladd
+ x: lreturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 15 4 0 arg1 J
- 15 4 2 arg2 J
+ 0 4 0 arg1 J
+ 0 4 2 arg2 J
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int nativeNonStaticAddToValue(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative, int);
descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
- stack=4, locals=2, args_size=2
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
- x: ldc #x // String nativeNonStaticAddToValue
- x: ldc #x // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: aload_0
- x: getfield #x // Field com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.value:I
- x: iload_1
- x: iadd
- x: ireturn
+ stack=2, locals=2, args_size=2
+ x: aload_0
+ x: getfield #x // Field com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.value:I
+ x: iload_1
+ x: iadd
+ x: ireturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 15 7 0 source Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
- 15 7 1 arg I
+ 0 7 0 source Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
+ 0 7 1 arg I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static byte nativeBytePlus(byte, byte);
descriptor: (BB)B
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
- stack=4, locals=2, args_size=2
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
- x: ldc #x // String nativeBytePlus
- x: ldc #x // String (BB)B
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: iload_0
- x: iload_1
- x: iadd
- x: i2b
- x: ireturn
+ stack=2, locals=2, args_size=2
+ x: iload_0
+ x: iload_1
+ x: iadd
+ x: i2b
+ x: ireturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 15 5 0 arg1 B
- 15 5 1 arg2 B
+ 0 5 0 arg1 B
+ 0 5 1 arg2 B
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ public static void notNativeRedirected(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;)V
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=0, locals=1, args_size=1
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 0 1 0 source Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ public static void notNativeStaticRedirected();
+ descriptor: ()V
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=0, locals=0, args_size=0
+ x: return
+ LineNumberTable:
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkNative_host.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassKeep
@@ -2974,7 +2492,7 @@
flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$1(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
@@ -2994,7 +2512,7 @@
0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
MethodParameters:
Name Flags
<no name> final mandated
@@ -3003,45 +2521,33 @@
descriptor: ()Ljava/lang/Integer;
flags: (0x0001) ACC_PUBLIC
Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Integer;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: iconst_1
- x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
- x: areturn
+ stack=1, locals=1, args_size=1
+ x: iconst_1
+ x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Object;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: aload_0
- x: invokevirtual #x // Method get:()Ljava/lang/Integer;
- x: areturn
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
@@ -3050,7 +2556,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -3075,51 +2581,39 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
flags: (0x0001) ACC_PUBLIC
Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Integer;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: iconst_2
- x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
- x: areturn
+ stack=1, locals=1, args_size=1
+ x: iconst_2
+ x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Object;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: aload_0
- x: invokevirtual #x // Method get:()Ljava/lang/Integer;
- x: areturn
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
@@ -3128,7 +2622,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -3144,7 +2638,7 @@
flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$3(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
@@ -3164,7 +2658,7 @@
0 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
MethodParameters:
Name Flags
<no name> final mandated
@@ -3173,45 +2667,33 @@
descriptor: ()Ljava/lang/Integer;
flags: (0x0001) ACC_PUBLIC
Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Integer;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: iconst_3
- x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
- x: areturn
+ stack=1, locals=1, args_size=1
+ x: iconst_3
+ x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Object;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: aload_0
- x: invokevirtual #x // Method get:()Ljava/lang/Integer;
- x: areturn
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
@@ -3220,7 +2702,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -3245,51 +2727,39 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
flags: (0x0001) ACC_PUBLIC
Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Integer;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: iconst_4
- x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
- x: areturn
+ stack=1, locals=1, args_size=1
+ x: iconst_4
+ x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Object;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: aload_0
- x: invokevirtual #x // Method get:()Ljava/lang/Integer;
- x: areturn
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
@@ -3298,7 +2768,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -3314,9 +2784,7 @@
flags: (0x0001) ACC_PUBLIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int);
descriptor: (I)V
@@ -3336,18 +2804,14 @@
0 10 1 x I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
- public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -3363,18 +2827,14 @@
flags: (0x0001) ACC_PUBLIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
@@ -3397,21 +2857,17 @@
0 15 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
MethodParameters:
Name Flags
<no name> final mandated
}
InnerClasses:
- public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -3436,51 +2892,39 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
flags: (0x0001) ACC_PUBLIC
Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Integer;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: bipush 7
- x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
- x: areturn
+ stack=1, locals=1, args_size=1
+ x: bipush 7
+ x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
+ x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 15 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+ 0 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
flags: (0x1041) ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Object;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: aload_0
- x: invokevirtual #x // Method get:()Ljava/lang/Integer;
- x: areturn
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: invokevirtual #x // Method get:()Ljava/lang/Integer;
+ x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 15 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+ 0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
@@ -3490,7 +2934,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -3506,9 +2950,7 @@
flags: (0x0001) ACC_PUBLIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass();
descriptor: ()V
@@ -3527,9 +2969,7 @@
0 11 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
@@ -3537,9 +2977,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -3555,9 +2993,7 @@
flags: (0x0001) ACC_PUBLIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass();
descriptor: ()V
@@ -3576,9 +3012,7 @@
0 11 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
descriptor: ()Ljava/util/function/Supplier;
@@ -3593,20 +3027,16 @@
Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
- public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
public static #x= #x of #x; // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -3633,19 +3063,15 @@
0 6 1 x I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
- public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -3662,9 +3088,7 @@
Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
descriptor: Ljava/util/function/Supplier;
@@ -3672,9 +3096,7 @@
Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses();
descriptor: ()V
@@ -3696,9 +3118,7 @@
0 17 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.util.function.Supplier<java.lang.Integer> getSupplier();
descriptor: ()Ljava/util/function/Supplier;
@@ -3717,9 +3137,7 @@
Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
descriptor: ()Ljava/util/function/Supplier;
@@ -3734,9 +3152,7 @@
Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
static {};
descriptor: ()V
@@ -3751,16 +3167,14 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
- public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
@@ -3769,12 +3183,10 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
NestMembers:
com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
@@ -3809,9 +3221,7 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int foo(int);
descriptor: (I)I
@@ -3830,19 +3240,15 @@
0 12 0 value I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkPackageRedirect.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.class
Compiled from "TinyFrameworkRenamedClassCaller.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller
@@ -3866,9 +3272,7 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int foo(int);
descriptor: (I)I
@@ -3887,19 +3291,15 @@
0 12 0 value I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkRenamedClassCaller.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
## Class: com/android/hoststubgen/test/tinyframework/packagetest/A.class
Compiled from "A.java"
public class com.android.hoststubgen.test.tinyframework.packagetest.A
@@ -3913,9 +3313,7 @@
SourceFile: "A.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/packagetest/sub/A.class
Compiled from "A.java"
public class com.android.hoststubgen.test.tinyframework.packagetest.sub.A
@@ -3929,9 +3327,7 @@
SourceFile: "A.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C1.class
Compiled from "C1.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.C1
@@ -3945,9 +3341,7 @@
SourceFile: "C1.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C2.class
Compiled from "C2.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
@@ -3961,9 +3355,7 @@
SourceFile: "C2.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C3.class
Compiled from "C3.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
@@ -3977,9 +3369,7 @@
SourceFile: "C3.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CA.class
Compiled from "CA.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.CA
@@ -3993,9 +3383,7 @@
SourceFile: "CA.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CB.class
Compiled from "CB.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.CB
@@ -4009,9 +3397,7 @@
SourceFile: "CB.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1.class
Compiled from "Class_C1.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C1 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
@@ -4025,7 +3411,7 @@
SourceFile: "Class_C1.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2.class
Compiled from "Class_C2.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
@@ -4039,7 +3425,7 @@
SourceFile: "Class_C2.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3.class
Compiled from "Class_C3.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C3
@@ -4053,7 +3439,7 @@
SourceFile: "Class_C3.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1.class
Compiled from "Class_I1.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1 implements com.android.hoststubgen.test.tinyframework.subclasstest.I1
@@ -4067,7 +3453,7 @@
SourceFile: "Class_I1.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA.class
Compiled from "Class_I1_IA.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1_IA implements com.android.hoststubgen.test.tinyframework.subclasstest.I1,com.android.hoststubgen.test.tinyframework.subclasstest.IA
@@ -4081,7 +3467,7 @@
SourceFile: "Class_I1_IA.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2.class
Compiled from "Class_I2.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I2 implements com.android.hoststubgen.test.tinyframework.subclasstest.I2
@@ -4095,7 +3481,7 @@
SourceFile: "Class_I2.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3.class
Compiled from "Class_I3.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3 implements com.android.hoststubgen.test.tinyframework.subclasstest.I3
@@ -4109,7 +3495,7 @@
SourceFile: "Class_I3.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I1.class
Compiled from "I1.java"
public interface com.android.hoststubgen.test.tinyframework.subclasstest.I1
@@ -4123,9 +3509,7 @@
SourceFile: "I1.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I2.class
Compiled from "I2.java"
public interface com.android.hoststubgen.test.tinyframework.subclasstest.I2 extends com.android.hoststubgen.test.tinyframework.subclasstest.I1
@@ -4139,9 +3523,7 @@
SourceFile: "I2.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I3.class
Compiled from "I3.java"
public interface com.android.hoststubgen.test.tinyframework.subclasstest.I3 extends com.android.hoststubgen.test.tinyframework.subclasstest.I2
@@ -4155,9 +3537,7 @@
SourceFile: "I3.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IA.class
Compiled from "IA.java"
public interface com.android.hoststubgen.test.tinyframework.subclasstest.IA
@@ -4171,9 +3551,7 @@
SourceFile: "IA.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IB.class
Compiled from "IB.java"
public interface com.android.hoststubgen.test.tinyframework.subclasstest.IB
@@ -4187,9 +3565,7 @@
SourceFile: "IB.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/supported/UnsupportedClass.class
Compiled from "UnsupportedClass.java"
public class com.supported.UnsupportedClass
@@ -4204,60 +3580,48 @@
flags: (0x0012) ACC_PRIVATE, ACC_FINAL
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public com.supported.UnsupportedClass(int);
descriptor: (I)V
flags: (0x0001) ACC_PUBLIC
Code:
- stack=4, locals=2, args_size=2
- x: ldc #x // String com/supported/UnsupportedClass
- x: ldc #x // String <init>
- x: ldc #x // String (I)V
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: aload_0
- x: invokespecial #x // Method java/lang/Object."<init>":()V
- x: aload_0
- x: iload_1
- x: putfield #x // Field mValue:I
- x: return
+ stack=2, locals=2, args_size=2
+ x: aload_0
+ x: invokespecial #x // Method java/lang/Object."<init>":()V
+ x: aload_0
+ x: iload_1
+ x: putfield #x // Field mValue:I
+ x: return
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 15 10 0 this Lcom/supported/UnsupportedClass;
- 15 10 1 value I
+ 0 10 0 this Lcom/supported/UnsupportedClass;
+ 0 10 1 value I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public int getValue();
descriptor: ()I
flags: (0x0001) ACC_PUBLIC
Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // String com/supported/UnsupportedClass
- x: ldc #x // String getValue
- x: ldc #x // String ()I
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: aload_0
- x: getfield #x // Field mValue:I
- x: ireturn
+ stack=1, locals=1, args_size=1
+ x: aload_0
+ x: getfield #x // Field mValue:I
+ x: ireturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 15 5 0 this Lcom/supported/UnsupportedClass;
+ 0 5 0 this Lcom/supported/UnsupportedClass;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "UnsupportedClass.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassKeep
@@ -4289,9 +3653,7 @@
0 14 1 value I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public int getValue();
descriptor: ()I
@@ -4309,19 +3671,15 @@
0 10 0 this Lcom/unsupported/UnsupportedClass;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "UnsupportedClass.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
## Class: rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.class
Compiled from "TinyFrameworkToBeRenamed.java"
public class rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed
@@ -4336,9 +3694,7 @@
flags: (0x0012) ACC_PRIVATE, ACC_FINAL
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed(int);
descriptor: (I)V
@@ -4358,9 +3714,7 @@
0 10 1 value I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public int getValue();
descriptor: ()I
@@ -4376,16 +3730,12 @@
0 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkToBeRenamed.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt
deleted file mode 100644
index 86a9c65..0000000
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/12-hoststubgen-test-tiny-framework-host-ext-stub-dump.txt
+++ /dev/null
@@ -1,2788 +0,0 @@
-## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy.class
- Compiled from "IPretendingAidl.java"
-public class com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub$Proxy
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 2, attributes: 4
- public com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub$Proxy();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int addTwo(int);
- descriptor: (I)I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
- public static #x= #x of #x; // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
-SourceFile: "IPretendingAidl.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl
-## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub.class
- Compiled from "IPretendingAidl.java"
-public class com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 2, attributes: 4
- public com.android.hoststubgen.test.tinyframework.IPretendingAidl$Stub();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int addOne(int);
- descriptor: (I)I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
- public static #x= #x of #x; // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
-SourceFile: "IPretendingAidl.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl
-## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl.class
- Compiled from "IPretendingAidl.java"
-public interface com.android.hoststubgen.test.tinyframework.IPretendingAidl
- minor version: 0
- major version: 61
- flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
- this_class: #x // com/android/hoststubgen/test/tinyframework/IPretendingAidl
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 0, attributes: 4
-}
-InnerClasses:
- public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
- public static #x= #x of #x; // Proxy=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy of class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
-SourceFile: "IPretendingAidl.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestMembers:
- com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
- com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy
-## Class: com/android/hoststubgen/test/tinyframework/R$Nested.class
- Compiled from "R.java"
-public class com.android.hoststubgen.test.tinyframework.R$Nested
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/R$Nested
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 2, attributes: 4
- public static int[] ARRAY;
- descriptor: [I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public com.android.hoststubgen.test.tinyframework.R$Nested();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- static {};
- descriptor: ()V
- flags: (0x0008) ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
-SourceFile: "R.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/R
-## Class: com/android/hoststubgen/test/tinyframework/R.class
- Compiled from "R.java"
-public class com.android.hoststubgen.test.tinyframework.R
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/R
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 1, attributes: 4
- public com.android.hoststubgen.test.tinyframework.R();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
-SourceFile: "R.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestMembers:
- com/android/hoststubgen/test/tinyframework/R$Nested
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.class
- Compiled from "TinyFrameworkAnnotations.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 5, attributes: 3
- public int stub;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkAnnotations();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public int addOne(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public int addTwo(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int nativeAddThree(int);
- descriptor: (I)I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public java.lang.String visibleButUsesUnsupportedMethod();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-}
-SourceFile: "TinyFrameworkAnnotations.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
- x: #x(#x=s#x)
- android.hosttest.annotation.HostSideTestClassLoadHook(
- value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
- )
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
- Compiled from "TinyFrameworkCallerCheck.java"
-class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
- minor version: 0
- major version: 61
- flags: (0x0020) ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 2, attributes: 4
- private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
- descriptor: ()V
- flags: (0x0002) ACC_PRIVATE
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int getOneStub();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-}
-InnerClasses:
- private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-SourceFile: "TinyFrameworkCallerCheck.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
- Compiled from "TinyFrameworkCallerCheck.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 3, attributes: 5
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int getOne_withCheck();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int getOne_noCheck();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-SourceFile: "TinyFrameworkCallerCheck.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-NestMembers:
- com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
- Compiled from "TinyFrameworkClassLoadHook.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 3, attributes: 3
- public static final java.util.Set<java.lang.Class<?>> sLoadedClasses;
- descriptor: Ljava/util/Set;
- flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
- Signature: #x // Ljava/util/Set<Ljava/lang/Class<*>;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook();
- descriptor: ()V
- flags: (0x0002) ACC_PRIVATE
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static void onClassLoaded(java.lang.Class<?>);
- descriptor: (Ljava/lang/Class;)V
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // (Ljava/lang/Class<*>;)V
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- static {};
- descriptor: ()V
- flags: (0x0008) ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkClassLoadHook.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.class
- Compiled from "TinyFrameworkClassWideAnnotations.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 4, attributes: 3
- public int stub;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int addOne(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int addTwo(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public java.lang.String visibleButUsesUnsupportedMethod();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkClassWideAnnotations.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.class
- Compiled from "TinyFrameworkClassWithInitializerDefault.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 2, methods: 0, attributes: 3
- public static boolean sInitialized;
- descriptor: Z
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public static java.lang.Object sObject;
- descriptor: Ljava/lang/Object;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
-}
-SourceFile: "TinyFrameworkClassWithInitializerDefault.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.class
- Compiled from "TinyFrameworkClassWithInitializerStub.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 2, methods: 0, attributes: 3
- public static boolean sInitialized;
- descriptor: Z
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public static java.lang.Object sObject;
- descriptor: Ljava/lang/Object;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
-}
-SourceFile: "TinyFrameworkClassWithInitializerStub.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x(#x=s#x)
- android.hosttest.annotation.HostSideTestClassLoadHook(
- value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
- )
- x: #x()
- android.hosttest.annotation.HostSideTestStub
- x: #x()
- android.hosttest.annotation.HostSideTestStaticInitializerKeep
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.class
- Compiled from "TinyFrameworkEnumComplex.java"
-public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex>
- minor version: 0
- major version: 61
- flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex
- super_class: #x // java/lang/Enum
- interfaces: 0, fields: 4, methods: 7, attributes: 4
- public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex RED;
- descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
- flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex GREEN;
- descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
- flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex BLUE;
- descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
- flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $VALUES;
- descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
- flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] values();
- descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex valueOf(java.lang.String);
- descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- MethodParameters:
- Name Flags
- <no name> mandated
-
- private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex(java.lang.String, java.lang.String);
- descriptor: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
- flags: (0x0002) ACC_PRIVATE
- Code:
- stack=3, locals=5, args_size=5
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // (Ljava/lang/String;Ljava/lang/String;)V
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
- MethodParameters:
- Name Flags
- <no name> synthetic
- <no name> synthetic
- <no name>
- <no name>
-
- public java.lang.String getLongName();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public java.lang.String getShortName();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $values();
- descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- static {};
- descriptor: ()V
- flags: (0x0008) ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;>;
-SourceFile: "TinyFrameworkEnumComplex.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.class
- Compiled from "TinyFrameworkEnumSimple.java"
-public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple>
- minor version: 0
- major version: 61
- flags: (0x4031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple
- super_class: #x // java/lang/Enum
- interfaces: 0, fields: 3, methods: 5, attributes: 4
- public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple CAT;
- descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
- flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple DOG;
- descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
- flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $VALUES;
- descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
- flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] values();
- descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple valueOf(java.lang.String);
- descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- MethodParameters:
- Name Flags
- <no name> mandated
-
- private com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple();
- descriptor: (Ljava/lang/String;I)V
- flags: (0x0002) ACC_PRIVATE
- Code:
- stack=3, locals=3, args_size=3
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // ()V
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- MethodParameters:
- Name Flags
- <no name> synthetic
- <no name> synthetic
-
- private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $values();
- descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- static {};
- descriptor: ()V
- flags: (0x0008) ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;>;
-SourceFile: "TinyFrameworkEnumSimple.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
- Compiled from "TinyFrameworkExceptionTester.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 2, attributes: 3
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int testException();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkExceptionTester.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
- Compiled from "TinyFrameworkForTextPolicy.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 14, attributes: 2
- public int stub;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int addOne(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public java.lang.String toBeIgnoredObj();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public void toBeIgnoredV();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public boolean toBeIgnoredZ();
- descriptor: ()Z
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public byte toBeIgnoredB();
- descriptor: ()B
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public char toBeIgnoredC();
- descriptor: ()C
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public short toBeIgnoredS();
- descriptor: ()S
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int toBeIgnoredI();
- descriptor: ()I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public float toBeIgnoredF();
- descriptor: ()F
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public double toBeIgnoredD();
- descriptor: ()D
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int addTwo(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int nativeAddThree(int);
- descriptor: (I)I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public java.lang.String visibleButUsesUnsupportedMethod();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkForTextPolicy.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.class
- Compiled from "TinyFrameworkLambdas.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 2, methods: 7, attributes: 5
- public final java.util.function.Supplier<java.lang.Integer> mSupplier;
- descriptor: Ljava/util/function/Supplier;
- flags: (0x0011) ACC_PUBLIC, ACC_FINAL
- Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
- descriptor: Ljava/util/function/Supplier;
- flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
- Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public java.util.function.Supplier<java.lang.Integer> getSupplier();
- descriptor: ()Ljava/util/function/Supplier;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
- descriptor: ()Ljava/util/function/Supplier;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- private static java.lang.Integer lambda$getSupplier_static$3();
- descriptor: ()Ljava/lang/Integer;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- private static java.lang.Integer lambda$getSupplier$2();
- descriptor: ()Ljava/lang/Integer;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- private static java.lang.Integer lambda$static$1();
- descriptor: ()Ljava/lang/Integer;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- private static java.lang.Integer lambda$new$0();
- descriptor: ()Ljava/lang/Integer;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
- public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
-SourceFile: "TinyFrameworkLambdas.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
- x: #x()
- android.hosttest.annotation.HostSideTestStaticInitializerKeep
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.class
- Compiled from "TinyFrameworkLambdas.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 2, methods: 7, attributes: 5
- public final java.util.function.Supplier<java.lang.Integer> mSupplier;
- descriptor: Ljava/util/function/Supplier;
- flags: (0x0011) ACC_PUBLIC, ACC_FINAL
- Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
- descriptor: Ljava/util/function/Supplier;
- flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
- Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public java.util.function.Supplier<java.lang.Integer> getSupplier();
- descriptor: ()Ljava/util/function/Supplier;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
- descriptor: ()Ljava/util/function/Supplier;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- private static java.lang.Integer lambda$getSupplier_static$3();
- descriptor: ()Ljava/lang/Integer;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- private static java.lang.Integer lambda$getSupplier$2();
- descriptor: ()Ljava/lang/Integer;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- private static java.lang.Integer lambda$static$1();
- descriptor: ()Ljava/lang/Integer;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- private static java.lang.Integer lambda$new$0();
- descriptor: ()Ljava/lang/Integer;
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
- public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
-SourceFile: "TinyFrameworkLambdas.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
- x: #x()
- android.hosttest.annotation.HostSideTestStaticInitializerKeep
-NestMembers:
- com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo.class
- Compiled from "TinyFrameworkMethodCallReplace.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 3, attributes: 4
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static void startThread(java.lang.Thread);
- descriptor: (Ljava/lang/Thread;)V
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int add(int, int);
- descriptor: (II)I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
-SourceFile: "TinyFrameworkMethodCallReplace.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class
- Compiled from "TinyFrameworkMethodCallReplace.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 4, attributes: 5
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static boolean nonStaticMethodCallReplaceTester() throws java.lang.Exception;
- descriptor: ()Z
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Exceptions:
- throws java.lang.Exception
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int staticMethodCallReplaceTester();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean);
- descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V
- flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
- public static final #x= #x of #x; // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
-SourceFile: "TinyFrameworkMethodCallReplace.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-NestMembers:
- com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.class
- Compiled from "TinyFrameworkNative.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNative
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 10, attributes: 3
- int value;
- descriptor: I
- flags: (0x0000)
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkNative();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static native int nativeAddTwo(int);
- descriptor: (I)I
- flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int nativeAddTwo_should_be_like_this(int);
- descriptor: (I)I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static native long nativeLongPlus(long, long);
- descriptor: (JJ)J
- flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static long nativeLongPlus_should_be_like_this(long, long);
- descriptor: (JJ)J
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=4, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public void setValue(int);
- descriptor: (I)V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public native int nativeNonStaticAddToValue(int);
- descriptor: (I)I
- flags: (0x0101) ACC_PUBLIC, ACC_NATIVE
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int nativeNonStaticAddToValue_should_be_like_this(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static void nativeStillNotSupported_should_be_like_this();
- descriptor: ()V
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static native byte nativeBytePlus(byte, byte);
- descriptor: (BB)B
- flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkNative.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
- x: #x(#x=s#x)
- android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
- value="TinyFrameworkNative_host"
- )
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
- Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 1, attributes: 4
- public int value;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass(int);
- descriptor: (I)V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class
- Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 2, methods: 1, attributes: 4
- public int value;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
- descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
- flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$InnerClass(com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses);
- descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;)V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- MethodParameters:
- Name Flags
- <no name> final mandated
-}
-InnerClasses:
- public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass.class
- Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 1, attributes: 4
- public int value;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
- public static #x= #x of #x; // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class
- Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 2, attributes: 4
- public int value;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$StaticNestedClass();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
- descriptor: ()Ljava/util/function/Supplier;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
- #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
- public static #x= #x of #x; // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class
- Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass extends com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$BaseClass
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
- super_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
- interfaces: 0, fields: 0, methods: 1, attributes: 4
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses$SubClass(int);
- descriptor: (I)V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
- public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class
- Compiled from "TinyFrameworkNestedClasses.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 2, methods: 4, attributes: 5
- public final java.util.function.Supplier<java.lang.Integer> mSupplier;
- descriptor: Ljava/util/function/Supplier;
- flags: (0x0011) ACC_PUBLIC, ACC_FINAL
- Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
- descriptor: Ljava/util/function/Supplier;
- flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL
- Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public java.util.function.Supplier<java.lang.Integer> getSupplier();
- descriptor: ()Ljava/util/function/Supplier;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
- descriptor: ()Ljava/util/function/Supplier;
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- static {};
- descriptor: ()V
- flags: (0x0008) ACC_STATIC
- Code:
- stack=3, locals=0, args_size=0
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
- #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
- #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
- #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
- public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
- public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
- public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
- public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
- public static #x= #x of #x; // Double$NestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
- #x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
-SourceFile: "TinyFrameworkNestedClasses.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-NestMembers:
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
- com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.class
- Compiled from "TinyFrameworkPackageRedirect.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 2, attributes: 3
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkPackageRedirect();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int foo(int);
- descriptor: (I)I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkPackageRedirect.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.class
- Compiled from "TinyFrameworkRenamedClassCaller.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 2, attributes: 3
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int foo(int);
- descriptor: (I)I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkRenamedClassCaller.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: com/android/hoststubgen/test/tinyframework/packagetest/A.class
- Compiled from "A.java"
-public class com.android.hoststubgen.test.tinyframework.packagetest.A
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/A
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "A.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/packagetest/sub/A.class
- Compiled from "A.java"
-public class com.android.hoststubgen.test.tinyframework.packagetest.sub.A
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/packagetest/sub/A
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "A.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C1.class
- Compiled from "C1.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.C1
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "C1.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C2.class
- Compiled from "C2.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2
- super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C1
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "C2.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C3.class
- Compiled from "C3.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C3
- super_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/C2
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "C3.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CA.class
- Compiled from "CA.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.CA
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CA
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "CA.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CB.class
- Compiled from "CB.java"
-public class com.android.hoststubgen.test.tinyframework.subclasstest.CB
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/CB
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "CB.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I1.class
- Compiled from "I1.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.I1
- minor version: 0
- major version: 61
- flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I1
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "I1.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I2.class
- Compiled from "I2.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.I2 extends com.android.hoststubgen.test.tinyframework.subclasstest.I1
- minor version: 0
- major version: 61
- flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I2
- super_class: #x // java/lang/Object
- interfaces: 1, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "I2.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I3.class
- Compiled from "I3.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.I3 extends com.android.hoststubgen.test.tinyframework.subclasstest.I2
- minor version: 0
- major version: 61
- flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/I3
- super_class: #x // java/lang/Object
- interfaces: 1, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "I3.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IA.class
- Compiled from "IA.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.IA
- minor version: 0
- major version: 61
- flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IA
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "IA.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IB.class
- Compiled from "IB.java"
-public interface com.android.hoststubgen.test.tinyframework.subclasstest.IB
- minor version: 0
- major version: 61
- flags: (0x0601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
- this_class: #x // com/android/hoststubgen/test/tinyframework/subclasstest/IB
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 0, attributes: 2
-}
-SourceFile: "IB.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-## Class: com/unsupported/UnsupportedClass.class
- Compiled from "UnsupportedClass.java"
-public class com.unsupported.UnsupportedClass
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/unsupported/UnsupportedClass
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 2, attributes: 3
- public com.unsupported.UnsupportedClass(int);
- descriptor: (I)V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int getValue();
- descriptor: ()I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "UnsupportedClass.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-## Class: rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.class
- Compiled from "TinyFrameworkToBeRenamed.java"
-public class rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 2, attributes: 3
- private final int mValue;
- descriptor: I
- flags: (0x0012) ACC_PRIVATE, ACC_FINAL
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed(int);
- descriptor: (I)V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=2, args_size=2
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int getValue();
- descriptor: ()I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=3, locals=1, args_size=1
- x: new #x // class java/lang/RuntimeException
- x: dup
- x: ldc #x // String Stub!
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
- x: athrow
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-SourceFile: "TinyFrameworkToBeRenamed.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
similarity index 78%
rename from tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt
rename to tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
index da434a6..41f459a 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-impl-dump.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/golden-output/13-hoststubgen-test-tiny-framework-host-ext-dump.txt
@@ -22,12 +22,12 @@
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "HostSideTestClassLoadHook.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -58,7 +58,7 @@
SourceFile: "HostSideTestKeep.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
@@ -67,13 +67,44 @@
java.lang.annotation.Retention(
value=Ljava/lang/annotation/RetentionPolicy;.CLASS
)
-## Class: android/hosttest/annotation/HostSideTestNativeSubstitutionClass.class
- Compiled from "HostSideTestNativeSubstitutionClass.java"
-public interface android.hosttest.annotation.HostSideTestNativeSubstitutionClass extends java.lang.annotation.Annotation
+## Class: android/hosttest/annotation/HostSideTestRedirect.class
+ Compiled from "HostSideTestRedirect.java"
+public interface android.hosttest.annotation.HostSideTestRedirect extends java.lang.annotation.Annotation
minor version: 0
major version: 61
flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
- this_class: #x // android/hosttest/annotation/HostSideTestNativeSubstitutionClass
+ this_class: #x // android/hosttest/annotation/HostSideTestRedirect
+ super_class: #x // java/lang/Object
+ interfaces: 1, fields: 0, methods: 1, attributes: 2
+ private static {};
+ descriptor: ()V
+ flags: (0x000a) ACC_PRIVATE, ACC_STATIC
+ Code:
+ stack=2, locals=0, args_size=0
+ x: ldc #x // class android/hosttest/annotation/HostSideTestRedirect
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
+ x: return
+}
+SourceFile: "HostSideTestRedirect.java"
+RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+ x: #x(#x=[e#x.#x])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.METHOD]
+ )
+ x: #x(#x=e#x.#x)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+## Class: android/hosttest/annotation/HostSideTestRedirectionClass.class
+ Compiled from "HostSideTestRedirectionClass.java"
+public interface android.hosttest.annotation.HostSideTestRedirectionClass extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 61
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #x // android/hosttest/annotation/HostSideTestRedirectionClass
super_class: #x // java/lang/Object
interfaces: 1, fields: 0, methods: 2, attributes: 2
private static {};
@@ -81,7 +112,7 @@
flags: (0x000a) ACC_PRIVATE, ACC_STATIC
Code:
stack=2, locals=0, args_size=0
- x: ldc #x // class android/hosttest/annotation/HostSideTestNativeSubstitutionClass
+ x: ldc #x // class android/hosttest/annotation/HostSideTestRedirectionClass
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -91,12 +122,12 @@
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
-SourceFile: "HostSideTestNativeSubstitutionClass.java"
+SourceFile: "HostSideTestRedirectionClass.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -127,7 +158,7 @@
SourceFile: "HostSideTestRemove.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
@@ -136,13 +167,13 @@
java.lang.annotation.Retention(
value=Ljava/lang/annotation/RetentionPolicy;.CLASS
)
-## Class: android/hosttest/annotation/HostSideTestStub.class
- Compiled from "HostSideTestStub.java"
-public interface android.hosttest.annotation.HostSideTestStub extends java.lang.annotation.Annotation
+## Class: android/hosttest/annotation/HostSideTestStaticInitializerKeep.class
+ Compiled from "HostSideTestStaticInitializerKeep.java"
+public interface android.hosttest.annotation.HostSideTestStaticInitializerKeep extends java.lang.annotation.Annotation
minor version: 0
major version: 61
flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
- this_class: #x // android/hosttest/annotation/HostSideTestStub
+ this_class: #x // android/hosttest/annotation/HostSideTestStaticInitializerKeep
super_class: #x // java/lang/Object
interfaces: 1, fields: 0, methods: 1, attributes: 2
private static {};
@@ -150,15 +181,15 @@
flags: (0x000a) ACC_PRIVATE, ACC_STATIC
Code:
stack=2, locals=0, args_size=0
- x: ldc #x // class android/hosttest/annotation/HostSideTestStub
+ x: ldc #x // class android/hosttest/annotation/HostSideTestStaticInitializerKeep
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
}
-SourceFile: "HostSideTestStub.java"
+SourceFile: "HostSideTestStaticInitializerKeep.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
x: #x(#x=[e#x.#x,e#x.#x,e#x.#x,e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
@@ -191,12 +222,12 @@
flags: (0x0401) ACC_PUBLIC, ACC_ABSTRACT
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "HostSideTestSubstitute.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.METHOD]
@@ -227,7 +258,7 @@
SourceFile: "HostSideTestThrow.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
x: #x(#x=[e#x.#x,e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR]
@@ -258,38 +289,7 @@
SourceFile: "HostSideTestWholeClassKeep.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- x: #x(#x=[e#x.#x])
- java.lang.annotation.Target(
- value=[Ljava/lang/annotation/ElementType;.TYPE]
- )
- x: #x(#x=e#x.#x)
- java.lang.annotation.Retention(
- value=Ljava/lang/annotation/RetentionPolicy;.CLASS
- )
-## Class: android/hosttest/annotation/HostSideTestWholeClassStub.class
- Compiled from "HostSideTestWholeClassStub.java"
-public interface android.hosttest.annotation.HostSideTestWholeClassStub extends java.lang.annotation.Annotation
- minor version: 0
- major version: 61
- flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
- this_class: #x // android/hosttest/annotation/HostSideTestWholeClassStub
- super_class: #x // java/lang/Object
- interfaces: 1, fields: 0, methods: 1, attributes: 2
- private static {};
- descriptor: ()V
- flags: (0x000a) ACC_PRIVATE, ACC_STATIC
- Code:
- stack=2, locals=0, args_size=0
- x: ldc #x // class android/hosttest/annotation/HostSideTestWholeClassStub
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
- x: return
-}
-SourceFile: "HostSideTestWholeClassStub.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
x: #x(#x=[e#x.#x])
java.lang.annotation.Target(
value=[Ljava/lang/annotation/ElementType;.TYPE]
@@ -313,7 +313,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -336,9 +336,7 @@
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int addTwo(int);
descriptor: (I)I
@@ -360,9 +358,7 @@
11 4 0 a I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
@@ -370,9 +366,7 @@
SourceFile: "IPretendingAidl.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl
## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub.class
Compiled from "IPretendingAidl.java"
@@ -389,7 +383,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -412,9 +406,7 @@
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int addOne(int);
descriptor: (I)I
@@ -436,9 +428,7 @@
11 4 0 a I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
public static #x= #x of #x; // Stub=class com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub of class com/android/hoststubgen/test/tinyframework/IPretendingAidl
@@ -446,9 +436,7 @@
SourceFile: "IPretendingAidl.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/IPretendingAidl
## Class: com/android/hoststubgen/test/tinyframework/IPretendingAidl.class
Compiled from "IPretendingAidl.java"
@@ -465,7 +453,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/IPretendingAidl
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
}
@@ -475,9 +463,7 @@
SourceFile: "IPretendingAidl.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestMembers:
com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub
com/android/hoststubgen/test/tinyframework/IPretendingAidl$Stub$Proxy
@@ -495,9 +481,7 @@
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public com.android.hoststubgen.test.tinyframework.R$Nested();
descriptor: ()V
@@ -518,9 +502,7 @@
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/R$Nested;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
static {};
descriptor: ()V
@@ -546,18 +528,14 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
- public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
+ public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
SourceFile: "R.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/R
## Class: com/android/hoststubgen/test/tinyframework/R.class
Compiled from "R.java"
@@ -574,7 +552,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/R
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -597,18 +575,14 @@
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/R;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/R$Nested of class com/android/hoststubgen/test/tinyframework/R
SourceFile: "R.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestMembers:
com/android/hoststubgen/test/tinyframework/R$Nested
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.class
@@ -619,25 +593,13 @@
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
super_class: #x // java/lang/Object
- interfaces: 0, fields: 2, methods: 8, attributes: 3
- public int stub;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
+ interfaces: 0, fields: 1, methods: 6, attributes: 3
public int keep;
descriptor: I
flags: (0x0001) ACC_PUBLIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestKeep
@@ -648,7 +610,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
x: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
@@ -669,23 +631,18 @@
x: invokespecial #x // Method java/lang/Object."<init>":()V
x: aload_0
x: iconst_1
- x: putfield #x // Field stub:I
- x: aload_0
- x: iconst_2
x: putfield #x // Field keep:I
x: return
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 11 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
+ 11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public int addOne(int);
descriptor: (I)I
@@ -697,40 +654,6 @@
x: ldc #x // String (I)I
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: aload_0
- x: iload_1
- x: invokevirtual #x // Method addOneInner:(I)I
- x: ireturn
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
- 11 6 1 value I
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-
- public int addOneInner(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=4, locals=2, args_size=2
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
- x: ldc #x // String addOneInner
- x: ldc #x // String (I)I
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
- x: ldc #x // String addOneInner
- x: ldc #x // String (I)I
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: iload_1
x: iconst_1
x: iadd
@@ -738,11 +661,11 @@
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
- 26 4 1 value I
+ 11 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
+ 11 4 1 value I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestKeep
@@ -770,9 +693,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int nativeAddThree(int);
descriptor: (I)I
@@ -796,9 +717,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.String unsupportedMethod();
descriptor: ()Ljava/lang/String;
@@ -810,12 +729,6 @@
x: ldc #x // String ()Ljava/lang/String;
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
- x: ldc #x // String unsupportedMethod
- x: ldc #x // String ()Ljava/lang/String;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
x: new #x // class java/lang/RuntimeException
x: dup
@@ -826,242 +739,22 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestThrow
-
- public java.lang.String visibleButUsesUnsupportedMethod();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations
- x: ldc #x // String visibleButUsesUnsupportedMethod
- x: ldc #x // String ()Ljava/lang/String;
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: aload_0
- x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
- x: areturn
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
}
SourceFile: "TinyFrameworkAnnotations.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
x: #x(#x=s#x)
android.hosttest.annotation.HostSideTestClassLoadHook(
value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
)
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.class
- Compiled from "TinyFrameworkCallerCheck.java"
-class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl
- minor version: 0
- major version: 61
- flags: (0x0020) ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 4, attributes: 4
- private static {};
- descriptor: ()V
- flags: (0x000a) ACC_PRIVATE, ACC_STATIC
- Code:
- stack=2, locals=0, args_size=0
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
- x: return
-
- private com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck$Impl();
- descriptor: ()V
- flags: (0x0002) ACC_PRIVATE
- Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
- x: ldc #x // String <init>
- x: ldc #x // String ()V
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: aload_0
- x: invokespecial #x // Method java/lang/Object."<init>":()V
- x: return
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int getOneKeep();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=4, locals=0, args_size=0
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
- x: ldc #x // String getOneKeep
- x: ldc #x // String ()I
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
- x: ldc #x // String getOneKeep
- x: ldc #x // String ()I
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: iconst_1
- x: ireturn
- LineNumberTable:
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestKeep
-
- public static int getOneStub();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=4, locals=0, args_size=0
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
- x: ldc #x // String getOneStub
- x: ldc #x // String ()I
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: iconst_1
- x: ireturn
- LineNumberTable:
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
- RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestStub
-}
-InnerClasses:
- private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-SourceFile: "TinyFrameworkCallerCheck.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.class
- Compiled from "TinyFrameworkCallerCheck.java"
-public class com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck
- minor version: 0
- major version: 61
- flags: (0x0021) ACC_PUBLIC, ACC_SUPER
- this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
- super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 4, attributes: 5
- private static {};
- descriptor: ()V
- flags: (0x000a) ACC_PRIVATE, ACC_STATIC
- Code:
- stack=2, locals=0, args_size=0
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
- x: return
-
- public com.android.hoststubgen.test.tinyframework.TinyFrameworkCallerCheck();
- descriptor: ()V
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
- x: ldc #x // String <init>
- x: ldc #x // String ()V
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: aload_0
- x: invokespecial #x // Method java/lang/Object."<init>":()V
- x: return
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int getOne_withCheck();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=4, locals=0, args_size=0
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
- x: ldc #x // String getOne_withCheck
- x: ldc #x // String ()I
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneKeep:()I
- x: ireturn
- LineNumberTable:
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public static int getOne_noCheck();
- descriptor: ()I
- flags: (0x0009) ACC_PUBLIC, ACC_STATIC
- Code:
- stack=4, locals=0, args_size=0
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
- x: ldc #x // String getOne_noCheck
- x: ldc #x // String ()I
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl.getOneStub:()I
- x: ireturn
- LineNumberTable:
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-}
-InnerClasses:
- private static #x= #x of #x; // Impl=class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl of class com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck
-SourceFile: "TinyFrameworkCallerCheck.java"
-RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-RuntimeInvisibleAnnotations:
- x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
-NestMembers:
- com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck$Impl
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.class
Compiled from "TinyFrameworkClassLoadHook.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook
@@ -1077,9 +770,7 @@
Signature: #x // Ljava/util/Set<Ljava/lang/Class<*>;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook();
descriptor: ()V
@@ -1100,9 +791,7 @@
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static void onClassLoaded(java.lang.Class<?>);
descriptor: (Ljava/lang/Class;)V
@@ -1129,9 +818,7 @@
Signature: #x // (Ljava/lang/Class<*>;)V
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
static {};
descriptor: ()V
@@ -1154,19 +841,15 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkClassLoadHook.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.class
Compiled from "TinyFrameworkClassWideAnnotations.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWideAnnotations
@@ -1175,15 +858,13 @@
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations
super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 6, attributes: 3
- public int stub;
+ interfaces: 0, fields: 1, methods: 5, attributes: 3
+ public int keep;
descriptor: I
flags: (0x0001) ACC_PUBLIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static {};
descriptor: ()V
@@ -1191,7 +872,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -1209,7 +890,7 @@
x: invokespecial #x // Method java/lang/Object."<init>":()V
x: aload_0
x: iconst_1
- x: putfield #x // Field stub:I
+ x: putfield #x // Field keep:I
x: return
LineNumberTable:
LocalVariableTable:
@@ -1217,9 +898,7 @@
11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public int addOne(int);
descriptor: (I)I
@@ -1242,9 +921,7 @@
11 4 1 value I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public int addTwo(int);
descriptor: (I)I
@@ -1269,9 +946,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.String unsupportedMethod();
descriptor: ()Ljava/lang/String;
@@ -1283,12 +958,6 @@
x: ldc #x // String ()Ljava/lang/String;
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations
- x: ldc #x // String unsupportedMethod
- x: ldc #x // String ()Ljava/lang/String;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
x: new #x // class java/lang/RuntimeException
x: dup
@@ -1299,43 +968,18 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestThrow
-
- public java.lang.String visibleButUsesUnsupportedMethod();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations
- x: ldc #x // String visibleButUsesUnsupportedMethod
- x: ldc #x // String ()Ljava/lang/String;
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: aload_0
- x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
- x: areturn
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
}
SourceFile: "TinyFrameworkClassWideAnnotations.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.class
Compiled from "TinyFrameworkClassWithInitializerDefault.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerDefault
@@ -1350,35 +994,29 @@
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static java.lang.Object sObject;
descriptor: Ljava/lang/Object;
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
}
SourceFile: "TinyFrameworkClassWithInitializerDefault.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.class
Compiled from "TinyFrameworkClassWithInitializerStub.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkClassWithInitializerStub
@@ -1393,24 +1031,20 @@
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static java.lang.Object sObject;
descriptor: Ljava/lang/Object;
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
static {};
descriptor: ()V
@@ -1438,21 +1072,19 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkClassWithInitializerStub.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x(#x=s#x)
android.hosttest.annotation.HostSideTestClassLoadHook(
value="com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded"
)
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
x: #x()
android.hosttest.annotation.HostSideTestStaticInitializerKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.class
@@ -1469,43 +1101,37 @@
flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex GREEN;
descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex BLUE;
descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
private final java.lang.String mLongName;
descriptor: Ljava/lang/String;
flags: (0x0012) ACC_PRIVATE, ACC_FINAL
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestKeep
@@ -1515,7 +1141,7 @@
flags: (0x0012) ACC_PRIVATE, ACC_FINAL
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestKeep
@@ -1525,9 +1151,7 @@
flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] values();
descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
@@ -1546,9 +1170,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex valueOf(java.lang.String);
descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
@@ -1571,9 +1193,7 @@
11 10 0 name Ljava/lang/String;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
MethodParameters:
Name Flags
<no name> mandated
@@ -1608,12 +1228,10 @@
Signature: #x // (Ljava/lang/String;Ljava/lang/String;)V
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
MethodParameters:
Name Flags
<no name> synthetic
@@ -1640,12 +1258,10 @@
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public java.lang.String getShortName();
descriptor: ()Ljava/lang/String;
@@ -1666,12 +1282,10 @@
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
private static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumComplex[] $values();
descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
@@ -1701,9 +1315,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
static {};
descriptor: ()V
@@ -1738,7 +1350,7 @@
x: dup
x: ldc #x // String BLUE
x: iconst_2
- x: ldc #x // String Blue
+ x: ldc #x // String Blue
x: ldc #x // String B
x: invokespecial #x // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
x: putstatic #x // Field BLUE:Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;
@@ -1748,20 +1360,16 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex;>;
SourceFile: "TinyFrameworkEnumComplex.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.class
Compiled from "TinyFrameworkEnumSimple.java"
public final class com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple extends java.lang.Enum<com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple>
@@ -1776,33 +1384,27 @@
flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple DOG;
descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
flags: (0x4019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
private static final com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] $VALUES;
descriptor: [Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
flags: (0x101a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple[] values();
descriptor: ()[Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
@@ -1821,9 +1423,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static com.android.hoststubgen.test.tinyframework.TinyFrameworkEnumSimple valueOf(java.lang.String);
descriptor: (Ljava/lang/String;)Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;
@@ -1846,9 +1446,7 @@
11 10 0 name Ljava/lang/String;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
MethodParameters:
Name Flags
<no name> mandated
@@ -1875,9 +1473,7 @@
Signature: #x // ()V
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
MethodParameters:
Name Flags
<no name> synthetic
@@ -1907,9 +1503,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
static {};
descriptor: ()V
@@ -1942,20 +1536,16 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
Signature: #x // Ljava/lang/Enum<Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple;>;
SourceFile: "TinyFrameworkEnumSimple.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.class
Compiled from "TinyFrameworkExceptionTester.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkExceptionTester
@@ -1971,7 +1561,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -1994,9 +1584,7 @@
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int testException();
descriptor: ()I
@@ -2032,19 +1620,15 @@
22 11 0 e Ljava/lang/Exception;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkExceptionTester.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.class
Compiled from "TinyFrameworkForTextPolicy.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkForTextPolicy
@@ -2053,22 +1637,13 @@
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
super_class: #x // java/lang/Object
- interfaces: 0, fields: 2, methods: 17, attributes: 2
+ interfaces: 0, fields: 1, methods: 15, attributes: 2
public int stub;
descriptor: I
flags: (0x0001) ACC_PUBLIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int keep;
- descriptor: I
- flags: (0x0001) ACC_PUBLIC
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static {};
descriptor: ()V
@@ -2076,7 +1651,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
x: ldc #x // String com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
@@ -2098,19 +1673,14 @@
x: aload_0
x: iconst_1
x: putfield #x // Field stub:I
- x: aload_0
- x: iconst_2
- x: putfield #x // Field keep:I
x: return
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 11 15 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 11 10 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public int addOne(int);
descriptor: (I)I
@@ -2122,37 +1692,6 @@
x: ldc #x // String (I)I
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: aload_0
- x: iload_1
- x: invokevirtual #x // Method addOneInner:(I)I
- x: ireturn
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
- 11 6 1 value I
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public int addOneInner(int);
- descriptor: (I)I
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=4, locals=2, args_size=2
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
- x: ldc #x // String addOneInner
- x: ldc #x // String (I)I
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
- x: ldc #x // String addOneInner
- x: ldc #x // String (I)I
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: iload_1
x: iconst_1
x: iadd
@@ -2160,11 +1699,11 @@
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
- 26 4 1 value I
+ 11 4 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
+ 11 4 1 value I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.String toBeIgnoredObj();
descriptor: ()Ljava/lang/String;
@@ -2182,9 +1721,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public void toBeIgnoredV();
descriptor: ()V
@@ -2201,9 +1738,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public boolean toBeIgnoredZ();
descriptor: ()Z
@@ -2221,9 +1756,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public byte toBeIgnoredB();
descriptor: ()B
@@ -2241,9 +1774,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public char toBeIgnoredC();
descriptor: ()C
@@ -2261,9 +1792,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public short toBeIgnoredS();
descriptor: ()S
@@ -2281,9 +1810,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public int toBeIgnoredI();
descriptor: ()I
@@ -2301,9 +1828,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public float toBeIgnoredF();
descriptor: ()F
@@ -2321,9 +1846,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public double toBeIgnoredD();
descriptor: ()D
@@ -2341,9 +1864,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsIgnore
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public int addTwo(int);
descriptor: (I)I
@@ -2351,7 +1872,7 @@
Code:
stack=4, locals=2, args_size=2
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
- x: ldc #x // String addTwo
+ x: ldc #x // String addTwo
x: ldc #x // String (I)I
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
@@ -2368,9 +1889,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int nativeAddThree(int);
descriptor: (I)I
@@ -2378,7 +1897,7 @@
Code:
stack=4, locals=1, args_size=1
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
- x: ldc #x // String nativeAddThree
+ x: ldc #x // String nativeAddThree
x: ldc #x // String (I)I
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
@@ -2394,9 +1913,7 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.String unsupportedMethod();
descriptor: ()Ljava/lang/String;
@@ -2404,57 +1921,26 @@
Code:
stack=4, locals=1, args_size=1
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
- x: ldc #x // String unsupportedMethod
+ x: ldc #x // String unsupportedMethod
x: ldc #x // String ()Ljava/lang/String;
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
- x: ldc #x // String unsupportedMethod
- x: ldc #x // String ()Ljava/lang/String;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
- x: new #x // class java/lang/RuntimeException
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
+ x: new #x // class java/lang/RuntimeException
x: dup
- x: ldc #x // String Unreachable
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ x: ldc #x // String Unreachable
+ x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
x: athrow
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
-
- public java.lang.String visibleButUsesUnsupportedMethod();
- descriptor: ()Ljava/lang/String;
- flags: (0x0001) ACC_PUBLIC
- Code:
- stack=4, locals=1, args_size=1
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy
- x: ldc #x // String visibleButUsesUnsupportedMethod
- x: ldc #x // String ()Ljava/lang/String;
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: aload_0
- x: invokevirtual #x // Method unsupportedMethod:()Ljava/lang/String;
- x: areturn
- LineNumberTable:
- LocalVariableTable:
- Start Length Slot Name Signature
- 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy;
- RuntimeVisibleAnnotations:
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkForTextPolicy.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested.class
Compiled from "TinyFrameworkLambdas.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested
@@ -2470,12 +1956,10 @@
Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
descriptor: Ljava/util/function/Supplier;
@@ -2483,12 +1967,10 @@
Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas$Nested();
descriptor: ()V
@@ -2512,12 +1994,10 @@
11 14 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public java.util.function.Supplier<java.lang.Integer> getSupplier();
descriptor: ()Ljava/util/function/Supplier;
@@ -2538,12 +2018,10 @@
Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
descriptor: ()Ljava/util/function/Supplier;
@@ -2561,12 +2039,10 @@
Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
private static java.lang.Integer lambda$getSupplier_static$3();
descriptor: ()Ljava/lang/Integer;
@@ -2584,9 +2060,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static java.lang.Integer lambda$getSupplier$2();
descriptor: ()Ljava/lang/Integer;
@@ -2604,9 +2078,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static java.lang.Integer lambda$static$1();
descriptor: ()Ljava/lang/Integer;
@@ -2624,9 +2096,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static java.lang.Integer lambda$new$0();
descriptor: ()Ljava/lang/Integer;
@@ -2644,9 +2114,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
static {};
descriptor: ()V
@@ -2662,12 +2130,12 @@
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier;
- x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier;
+ x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier;
x: return
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
@@ -2675,12 +2143,10 @@
SourceFile: "TinyFrameworkLambdas.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
x: #x()
android.hosttest.annotation.HostSideTestStaticInitializerKeep
BootstrapMethods:
@@ -2720,12 +2186,10 @@
Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
descriptor: Ljava/util/function/Supplier;
@@ -2733,12 +2197,10 @@
Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public com.android.hoststubgen.test.tinyframework.TinyFrameworkLambdas();
descriptor: ()V
@@ -2762,12 +2224,10 @@
11 14 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public java.util.function.Supplier<java.lang.Integer> getSupplier();
descriptor: ()Ljava/util/function/Supplier;
@@ -2788,12 +2248,10 @@
Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
descriptor: ()Ljava/util/function/Supplier;
@@ -2811,12 +2269,10 @@
Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
private static java.lang.Integer lambda$getSupplier_static$3();
descriptor: ()Ljava/lang/Integer;
@@ -2834,9 +2290,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static java.lang.Integer lambda$getSupplier$2();
descriptor: ()Ljava/lang/Integer;
@@ -2854,9 +2308,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static java.lang.Integer lambda$static$1();
descriptor: ()Ljava/lang/Integer;
@@ -2874,9 +2326,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static java.lang.Integer lambda$new$0();
descriptor: ()Ljava/lang/Integer;
@@ -2894,9 +2344,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
static {};
descriptor: ()V
@@ -2912,12 +2360,12 @@
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: invokedynamic #x, 0 // InvokeDynamic #x:get:()Ljava/util/function/Supplier;
- x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier;
+ x: putstatic #x // Field sSupplier:Ljava/util/function/Supplier;
x: return
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
public static #x= #x of #x; // Nested=class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas$Nested of class com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas
@@ -2925,12 +2373,10 @@
SourceFile: "TinyFrameworkLambdas.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestStub
+ android.hosttest.annotation.HostSideTestKeep
x: #x()
android.hosttest.annotation.HostSideTestStaticInitializerKeep
BootstrapMethods:
@@ -2971,7 +2417,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -2994,9 +2440,7 @@
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static void startThread(java.lang.Thread);
descriptor: (Ljava/lang/Thread;)V
@@ -3020,9 +2464,7 @@
11 10 0 thread Ljava/lang/Thread;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int add(int, int);
descriptor: (II)I
@@ -3045,18 +2487,14 @@
11 4 1 b I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
SourceFile: "TinyFrameworkMethodCallReplace.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.class
Compiled from "TinyFrameworkMethodCallReplace.java"
@@ -3073,7 +2511,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -3096,9 +2534,7 @@
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static boolean nonStaticMethodCallReplaceTester() throws java.lang.Exception;
descriptor: ()Z
@@ -3137,9 +2573,7 @@
throws java.lang.Exception
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int staticMethodCallReplaceTester();
descriptor: ()I
@@ -3158,9 +2592,7 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static void lambda$nonStaticMethodCallReplaceTester$0(java.util.concurrent.atomic.AtomicBoolean);
descriptor: (Ljava/util/concurrent/atomic/AtomicBoolean;)V
@@ -3173,7 +2605,7 @@
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
x: aload_0
- x: invokestatic #x // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
+ x: invokestatic #x // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
x: invokevirtual #x // Method java/lang/Thread.isDaemon:()Z
x: invokevirtual #x // Method java/util/concurrent/atomic/AtomicBoolean.set:(Z)V
x: return
@@ -3183,9 +2615,7 @@
11 11 0 ab Ljava/util/concurrent/atomic/AtomicBoolean;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
public static #x= #x of #x; // ReplaceTo=class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace$ReplaceTo of class com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace
@@ -3193,12 +2623,10 @@
SourceFile: "TinyFrameworkMethodCallReplace.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
BootstrapMethods:
x: #x REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
@@ -3215,15 +2643,13 @@
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
super_class: #x // java/lang/Object
- interfaces: 0, fields: 1, methods: 12, attributes: 3
+ interfaces: 0, fields: 1, methods: 15, attributes: 3
int value;
descriptor: I
flags: (0x0000)
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static {};
descriptor: ()V
@@ -3231,7 +2657,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -3254,9 +2680,7 @@
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int nativeAddTwo(int);
descriptor: (I)I
@@ -3275,9 +2699,10 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+ RuntimeInvisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ android.hosttest.annotation.HostSideTestRedirect
public static int nativeAddTwo_should_be_like_this(int);
descriptor: (I)I
@@ -3298,9 +2723,7 @@
11 5 0 arg I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static long nativeLongPlus(long, long);
descriptor: (JJ)J
@@ -3320,9 +2743,10 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+ RuntimeInvisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ android.hosttest.annotation.HostSideTestRedirect
public static long nativeLongPlus_should_be_like_this(long, long);
descriptor: (JJ)J
@@ -3345,9 +2769,7 @@
11 6 2 arg2 J
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public void setValue(int);
descriptor: (I)V
@@ -3370,9 +2792,7 @@
11 6 1 v I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public int nativeNonStaticAddToValue(int);
descriptor: (I)I
@@ -3392,9 +2812,10 @@
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+ RuntimeInvisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ android.hosttest.annotation.HostSideTestRedirect
public int nativeNonStaticAddToValue_should_be_like_this(int);
descriptor: (I)I
@@ -3417,9 +2838,7 @@
11 6 1 arg I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static void nativeStillNotSupported();
descriptor: ()V
@@ -3431,49 +2850,46 @@
x: ldc #x // String ()V
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
- x: ldc #x // String nativeStillNotSupported
- x: ldc #x // String ()V
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onThrowMethodCalled:()V
x: new #x // class java/lang/RuntimeException
x: dup
x: ldc #x // String Unreachable
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
+ x: invokespecial #x // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
x: athrow
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsThrow
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestThrow
+ public static native void nativeStillKeep();
+ descriptor: ()V
+ flags: (0x0109) ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
public static void nativeStillNotSupported_should_be_like_this();
descriptor: ()V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
- x: ldc #x // String nativeStillNotSupported_should_be_like_this
+ x: ldc #x // String nativeStillNotSupported_should_be_like_this
x: ldc #x // String ()V
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
x: new #x // class java/lang/RuntimeException
x: dup
- x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V
+ x: invokespecial #x // Method java/lang/RuntimeException."<init>":()V
x: athrow
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static byte nativeBytePlus(byte, byte);
descriptor: (BB)B
@@ -3481,33 +2897,75 @@
Code:
stack=4, locals=2, args_size=2
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
- x: ldc #x // String nativeBytePlus
- x: ldc #x // String (BB)B
+ x: ldc #x // String nativeBytePlus
+ x: ldc #x // String (BB)B
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
x: iload_0
x: iload_1
- x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeBytePlus:(BB)B
+ x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.nativeBytePlus:(BB)B
x: ireturn
RuntimeVisibleAnnotations:
x: #x()
com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+ RuntimeInvisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ android.hosttest.annotation.HostSideTestRedirect
+
+ public void notNativeRedirected();
+ descriptor: ()V
+ flags: (0x0001) ACC_PUBLIC
+ Code:
+ stack=4, locals=1, args_size=1
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
+ x: ldc #x // String notNativeRedirected
+ x: ldc #x // String ()V
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ x: aload_0
+ x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.notNativeRedirected:(Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;)V
+ x: return
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+ RuntimeInvisibleAnnotations:
+ x: #x()
+ android.hosttest.annotation.HostSideTestRedirect
+
+ public static void notNativeStaticRedirected();
+ descriptor: ()V
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative
+ x: ldc #x // String notNativeStaticRedirected
+ x: ldc #x // String ()V
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ x: invokestatic #x // Method com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.notNativeStaticRedirected:()V
+ x: return
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsSubstitute
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+ RuntimeInvisibleAnnotations:
+ x: #x()
+ android.hosttest.annotation.HostSideTestRedirect
}
SourceFile: "TinyFrameworkNative.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
x: #x(#x=s#x)
- android.hosttest.annotation.HostSideTestNativeSubstitutionClass(
+ android.hosttest.annotation.HostSideTestRedirectionClass(
value="TinyFrameworkNative_host"
)
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.class
@@ -3518,7 +2976,7 @@
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #x // com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
super_class: #x // java/lang/Object
- interfaces: 0, fields: 0, methods: 6, attributes: 3
+ interfaces: 0, fields: 0, methods: 8, attributes: 3
private static {};
descriptor: ()V
flags: (0x000a) ACC_PRIVATE, ACC_STATIC
@@ -3539,22 +2997,16 @@
x: ldc #x // String ()V
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
- x: ldc #x // String <init>
- x: ldc #x // String ()V
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: aload_0
x: invokespecial #x // Method java/lang/Object."<init>":()V
x: return
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host;
+ 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int nativeAddTwo(int);
descriptor: (I)I
@@ -3566,12 +3018,6 @@
x: ldc #x // String (I)I
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
- x: ldc #x // String nativeAddTwo
- x: ldc #x // String (I)I
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: iload_0
x: iconst_2
x: iadd
@@ -3579,10 +3025,10 @@
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 4 0 arg I
+ 11 4 0 arg I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static long nativeLongPlus(long, long);
descriptor: (JJ)J
@@ -3594,12 +3040,6 @@
x: ldc #x // String (JJ)J
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
- x: ldc #x // String nativeLongPlus
- x: ldc #x // String (JJ)J
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: lload_0
x: lload_2
x: ladd
@@ -3607,11 +3047,11 @@
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 4 0 arg1 J
- 26 4 2 arg2 J
+ 11 4 0 arg1 J
+ 11 4 2 arg2 J
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int nativeNonStaticAddToValue(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative, int);
descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I
@@ -3623,12 +3063,6 @@
x: ldc #x // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
- x: ldc #x // String nativeNonStaticAddToValue
- x: ldc #x // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;I)I
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: aload_0
x: getfield #x // Field com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.value:I
x: iload_1
@@ -3637,11 +3071,11 @@
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 7 0 source Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
- 26 7 1 arg I
+ 11 7 0 source Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
+ 11 7 1 arg I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static byte nativeBytePlus(byte, byte);
descriptor: (BB)B
@@ -3653,12 +3087,6 @@
x: ldc #x // String (BB)B
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
- x: ldc #x // String nativeBytePlus
- x: ldc #x // String (BB)B
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: iload_0
x: iload_1
x: iadd
@@ -3667,16 +3095,51 @@
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 5 0 arg1 B
- 26 5 1 arg2 B
+ 11 5 0 arg1 B
+ 11 5 1 arg2 B
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ public static void notNativeRedirected(com.android.hoststubgen.test.tinyframework.TinyFrameworkNative);
+ descriptor: (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;)V
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=1, args_size=1
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+ x: ldc #x // String notNativeRedirected
+ x: ldc #x // String (Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;)V
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ x: return
+ LineNumberTable:
+ LocalVariableTable:
+ Start Length Slot Name Signature
+ 11 1 0 source Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNative;
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
+
+ public static void notNativeStaticRedirected();
+ descriptor: ()V
+ flags: (0x0009) ACC_PUBLIC, ACC_STATIC
+ Code:
+ stack=4, locals=0, args_size=0
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host
+ x: ldc #x // String notNativeStaticRedirected
+ x: ldc #x // String ()V
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
+ x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ x: return
+ LineNumberTable:
+ RuntimeVisibleAnnotations:
+ x: #x()
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkNative_host.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassKeep
@@ -3694,7 +3157,7 @@
flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static {};
descriptor: ()V
@@ -3729,7 +3192,7 @@
11 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
MethodParameters:
Name Flags
<no name> final mandated
@@ -3744,22 +3207,16 @@
x: ldc #x // String ()Ljava/lang/Integer;
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Integer;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: iconst_1
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+ 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
@@ -3771,22 +3228,16 @@
x: ldc #x // String ()Ljava/lang/Object;
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Object;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: aload_0
x: invokevirtual #x // Method get:()Ljava/lang/Integer;
x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
+ 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
@@ -3795,7 +3246,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -3835,7 +3286,7 @@
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -3847,22 +3298,16 @@
x: ldc #x // String ()Ljava/lang/Integer;
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Integer;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: iconst_2
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+ 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
@@ -3874,22 +3319,16 @@
x: ldc #x // String ()Ljava/lang/Object;
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Object;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: aload_0
x: invokevirtual #x // Method get:()Ljava/lang/Integer;
x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
+ 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
@@ -3898,7 +3337,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -3914,7 +3353,7 @@
flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static {};
descriptor: ()V
@@ -3949,7 +3388,7 @@
11 10 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
MethodParameters:
Name Flags
<no name> final mandated
@@ -3964,22 +3403,16 @@
x: ldc #x // String ()Ljava/lang/Integer;
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Integer;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: iconst_3
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+ 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
@@ -3991,22 +3424,16 @@
x: ldc #x // String ()Ljava/lang/Object;
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Object;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: aload_0
x: invokevirtual #x // Method get:()Ljava/lang/Integer;
x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
+ 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
@@ -4015,7 +3442,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -4055,7 +3482,7 @@
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -4067,22 +3494,16 @@
x: ldc #x // String ()Ljava/lang/Integer;
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Integer;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: iconst_4
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+ 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
@@ -4094,22 +3515,16 @@
x: ldc #x // String ()Ljava/lang/Object;
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Object;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: aload_0
x: invokevirtual #x // Method get:()Ljava/lang/Integer;
x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
+ 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
@@ -4118,7 +3533,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -4134,9 +3549,7 @@
flags: (0x0001) ACC_PUBLIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static {};
descriptor: ()V
@@ -4144,7 +3557,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -4171,18 +3584,14 @@
11 10 1 x I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -4198,18 +3607,14 @@
flags: (0x0001) ACC_PUBLIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
final com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses this$0;
descriptor: Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static {};
descriptor: ()V
@@ -4217,7 +3622,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -4247,9 +3652,7 @@
11 15 1 this$0 Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
MethodParameters:
Name Flags
<no name> final mandated
@@ -4259,9 +3662,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -4301,7 +3702,7 @@
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.Integer get();
descriptor: ()Ljava/lang/Integer;
@@ -4313,22 +3714,16 @@
x: ldc #x // String ()Ljava/lang/Integer;
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Integer;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: bipush 7
x: invokestatic #x // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+ 11 6 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.lang.Object get();
descriptor: ()Ljava/lang/Object;
@@ -4340,22 +3735,16 @@
x: ldc #x // String ()Ljava/lang/Object;
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1
- x: ldc #x // String get
- x: ldc #x // String ()Ljava/lang/Object;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: aload_0
x: invokevirtual #x // Method get:()Ljava/lang/Integer;
x: areturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
+ 11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$1;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
@@ -4365,7 +3754,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -4381,9 +3770,7 @@
flags: (0x0001) ACC_PUBLIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static {};
descriptor: ()V
@@ -4391,7 +3778,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -4417,9 +3804,7 @@
11 11 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass$Double$NestedClass;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
@@ -4427,9 +3812,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -4445,9 +3828,7 @@
flags: (0x0001) ACC_PUBLIC
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static {};
descriptor: ()V
@@ -4455,7 +3836,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -4481,9 +3862,7 @@
11 11 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
descriptor: ()Ljava/util/function/Supplier;
@@ -4503,9 +3882,7 @@
Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
@@ -4514,9 +3891,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -4533,7 +3908,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -4558,9 +3933,7 @@
11 6 1 x I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
@@ -4568,9 +3941,7 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
NestHost: class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.class
Compiled from "TinyFrameworkNestedClasses.java"
@@ -4587,9 +3958,7 @@
Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static final java.util.function.Supplier<java.lang.Integer> sSupplier;
descriptor: Ljava/util/function/Supplier;
@@ -4597,9 +3966,7 @@
Signature: #x // Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public com.android.hoststubgen.test.tinyframework.TinyFrameworkNestedClasses();
descriptor: ()V
@@ -4626,9 +3993,7 @@
11 17 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public java.util.function.Supplier<java.lang.Integer> getSupplier();
descriptor: ()Ljava/util/function/Supplier;
@@ -4652,9 +4017,7 @@
Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static java.util.function.Supplier<java.lang.Integer> getSupplier_static();
descriptor: ()Ljava/util/function/Supplier;
@@ -4674,9 +4037,7 @@
Signature: #x // ()Ljava/util/function/Supplier<Ljava/lang/Integer;>;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
static {};
descriptor: ()V
@@ -4699,16 +4060,14 @@
LineNumberTable:
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
InnerClasses:
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$1
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$3
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$4
#x; // class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$2
- public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
+ public static #x= #x of #x; // SubClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
public static #x= #x of #x; // BaseClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
public static #x= #x of #x; // StaticNestedClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$StaticNestedClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
public #x= #x of #x; // InnerClass=class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$InnerClass of class com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses
@@ -4717,12 +4076,10 @@
SourceFile: "TinyFrameworkNestedClasses.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
NestMembers:
com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$SubClass
com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses$BaseClass
@@ -4749,7 +4106,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -4772,9 +4129,7 @@
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int foo(int);
descriptor: (I)I
@@ -4798,19 +4153,15 @@
11 12 0 value I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkPackageRedirect.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
## Class: com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.class
Compiled from "TinyFrameworkRenamedClassCaller.java"
public class com.android.hoststubgen.test.tinyframework.TinyFrameworkRenamedClassCaller
@@ -4826,7 +4177,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -4849,9 +4200,7 @@
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public static int foo(int);
descriptor: (I)I
@@ -4875,19 +4224,15 @@
11 12 0 value I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkRenamedClassCaller.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
## Class: com/android/hoststubgen/test/tinyframework/packagetest/A.class
Compiled from "A.java"
public class com.android.hoststubgen.test.tinyframework.packagetest.A
@@ -4903,16 +4248,14 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/packagetest/A
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
}
SourceFile: "A.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/packagetest/sub/A.class
Compiled from "A.java"
public class com.android.hoststubgen.test.tinyframework.packagetest.sub.A
@@ -4928,16 +4271,14 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/packagetest/sub/A
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
}
SourceFile: "A.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C1.class
Compiled from "C1.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.C1
@@ -4953,16 +4294,14 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/C1
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
}
SourceFile: "C1.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C2.class
Compiled from "C2.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
@@ -4978,16 +4317,14 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/C2
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
}
SourceFile: "C2.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/C3.class
Compiled from "C3.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
@@ -5003,16 +4340,14 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/C3
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
}
SourceFile: "C3.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CA.class
Compiled from "CA.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.CA
@@ -5028,16 +4363,14 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/CA
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
}
SourceFile: "CA.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/CB.class
Compiled from "CB.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.CB
@@ -5053,16 +4386,14 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/CB
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
}
SourceFile: "CB.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C1.class
Compiled from "Class_C1.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C1 extends com.android.hoststubgen.test.tinyframework.subclasstest.C1
@@ -5085,7 +4416,7 @@
SourceFile: "Class_C1.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C2.class
Compiled from "Class_C2.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C2 extends com.android.hoststubgen.test.tinyframework.subclasstest.C2
@@ -5108,7 +4439,7 @@
SourceFile: "Class_C2.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_C3.class
Compiled from "Class_C3.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_C3 extends com.android.hoststubgen.test.tinyframework.subclasstest.C3
@@ -5131,7 +4462,7 @@
SourceFile: "Class_C3.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1.class
Compiled from "Class_I1.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1 implements com.android.hoststubgen.test.tinyframework.subclasstest.I1
@@ -5154,7 +4485,7 @@
SourceFile: "Class_I1.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I1_IA.class
Compiled from "Class_I1_IA.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I1_IA implements com.android.hoststubgen.test.tinyframework.subclasstest.I1,com.android.hoststubgen.test.tinyframework.subclasstest.IA
@@ -5177,7 +4508,7 @@
SourceFile: "Class_I1_IA.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I2.class
Compiled from "Class_I2.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I2 implements com.android.hoststubgen.test.tinyframework.subclasstest.I2
@@ -5200,7 +4531,7 @@
SourceFile: "Class_I2.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/Class_I3.class
Compiled from "Class_I3.java"
public class com.android.hoststubgen.test.tinyframework.subclasstest.Class_I3 implements com.android.hoststubgen.test.tinyframework.subclasstest.I3
@@ -5223,7 +4554,7 @@
SourceFile: "Class_I3.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I1.class
Compiled from "I1.java"
public interface com.android.hoststubgen.test.tinyframework.subclasstest.I1
@@ -5239,16 +4570,14 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/I1
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
}
SourceFile: "I1.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I2.class
Compiled from "I2.java"
public interface com.android.hoststubgen.test.tinyframework.subclasstest.I2 extends com.android.hoststubgen.test.tinyframework.subclasstest.I1
@@ -5271,9 +4600,7 @@
SourceFile: "I2.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/I3.class
Compiled from "I3.java"
public interface com.android.hoststubgen.test.tinyframework.subclasstest.I3 extends com.android.hoststubgen.test.tinyframework.subclasstest.I2
@@ -5296,9 +4623,7 @@
SourceFile: "I3.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IA.class
Compiled from "IA.java"
public interface com.android.hoststubgen.test.tinyframework.subclasstest.IA
@@ -5314,16 +4639,14 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/IA
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
}
SourceFile: "IA.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/android/hoststubgen/test/tinyframework/subclasstest/IB.class
Compiled from "IB.java"
public interface com.android.hoststubgen.test.tinyframework.subclasstest.IB
@@ -5339,16 +4662,14 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/android/hoststubgen/test/tinyframework/subclasstest/IB
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
}
SourceFile: "IB.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
## Class: com/supported/UnsupportedClass.class
Compiled from "UnsupportedClass.java"
public class com.supported.UnsupportedClass
@@ -5363,7 +4684,7 @@
flags: (0x0012) ACC_PRIVATE, ACC_FINAL
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static {};
descriptor: ()V
@@ -5385,12 +4706,6 @@
x: ldc #x // String (I)V
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/supported/UnsupportedClass
- x: ldc #x // String <init>
- x: ldc #x // String (I)V
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: aload_0
x: invokespecial #x // Method java/lang/Object."<init>":()V
x: aload_0
@@ -5400,11 +4715,11 @@
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 10 0 this Lcom/supported/UnsupportedClass;
- 26 10 1 value I
+ 11 10 0 this Lcom/supported/UnsupportedClass;
+ 11 10 1 value I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public int getValue();
descriptor: ()I
@@ -5416,27 +4731,21 @@
x: ldc #x // String ()I
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.callMethodCallHook:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
- x: ldc #x // String com/supported/UnsupportedClass
- x: ldc #x // String getValue
- x: ldc #x // String ()I
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.getStackWalker:()Ljava/lang/StackWalker;
- x: invokevirtual #x // Method java/lang/StackWalker.getCallerClass:()Ljava/lang/Class;
- x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onNonStubMethodCalled:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;)V
x: aload_0
x: getfield #x // Field mValue:I
x: ireturn
LineNumberTable:
LocalVariableTable:
Start Length Slot Name Signature
- 26 5 0 this Lcom/supported/UnsupportedClass;
+ 11 5 0 this Lcom/supported/UnsupportedClass;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "UnsupportedClass.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
android.hosttest.annotation.HostSideTestWholeClassKeep
@@ -5455,7 +4764,7 @@
Code:
stack=2, locals=0, args_size=0
x: ldc #x // class com/unsupported/UnsupportedClass
- x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
+ x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -5483,9 +4792,7 @@
11 14 1 value I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public int getValue();
descriptor: ()I
@@ -5508,19 +4815,15 @@
11 10 0 this Lcom/unsupported/UnsupportedClass;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "UnsupportedClass.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
## Class: rename_prefix/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.class
Compiled from "TinyFrameworkToBeRenamed.java"
public class rename_prefix.com.android.hoststubgen.test.tinyframework.TinyFrameworkToBeRenamed
@@ -5535,16 +4838,14 @@
flags: (0x0012) ACC_PRIVATE, ACC_FINAL
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
private static {};
descriptor: ()V
flags: (0x000a) ACC_PRIVATE, ACC_STATIC
Code:
stack=2, locals=0, args_size=0
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logClassLoaded
x: invokestatic #x // Method com/android/hoststubgen/hosthelper/HostTestUtils.onClassLoaded:(Ljava/lang/Class;Ljava/lang/String;)V
x: return
@@ -5554,7 +4855,7 @@
flags: (0x0001) ACC_PUBLIC
Code:
stack=4, locals=2, args_size=2
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
x: ldc #x // String <init>
x: ldc #x // String (I)V
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
@@ -5572,16 +4873,14 @@
11 10 1 value I
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
public int getValue();
descriptor: ()I
flags: (0x0001) ACC_PUBLIC
Code:
stack=4, locals=1, args_size=1
- x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
+ x: ldc #x // class com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed
x: ldc #x // String getValue
x: ldc #x // String ()I
x: ldc #x // String com.android.hoststubgen.hosthelper.HostTestUtils.logMethodCall
@@ -5595,16 +4894,12 @@
11 5 0 this Lcom/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed;
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
}
SourceFile: "TinyFrameworkToBeRenamed.java"
RuntimeVisibleAnnotations:
x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInStub
- x: #x()
- com.android.hoststubgen.hosthelper.HostStubGenKeptInImpl
+ com.android.hoststubgen.hosthelper.HostStubGenProcessedAsKeep
RuntimeInvisibleAnnotations:
x: #x()
- android.hosttest.annotation.HostSideTestWholeClassStub
+ android.hosttest.annotation.HostSideTestWholeClassKeep
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt b/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
index f064433..3c138d2 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/policy-override-tiny-framework.txt
@@ -1,9 +1,8 @@
-class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy stub
- field stub stub
- field keep keep
+class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy keep
+ field stub keep
# field remove remove # Implicitly remove
- method <init> ()V stub
- method addOne (I)I stub
+ method <init> ()V keep
+ method addOne (I)I keep
method addOneInner (I)I keep
method toBeRemoved (Ljava/lang/String;)V remove
method addTwo (I)I @addTwo_host
@@ -11,7 +10,7 @@
method nativeAddThree (I)I @addThree_host
# method addThree_host (I)I # used as a substitute
method unsupportedMethod ()Ljava/lang/String; throw
- method visibleButUsesUnsupportedMethod ()Ljava/lang/String; stub
+ method visibleButUsesUnsupportedMethod ()Ljava/lang/String; keep
method toBeIgnoredObj ()Ljava/lang/String; ignore
method toBeIgnoredV ()V ignore
method toBeIgnoredZ ()Z ignore
@@ -27,22 +26,22 @@
class com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy ~com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded
# Heuristics rule: Stub all the AIDL classes.
-class :aidl stubclass
+class :aidl keepclass
# Heuristics rule: Stub all the R classes.
-class :r stubclass
+class :r keepclass
# Default is "remove", so let's put all the base classes / interfaces in the stub first.
-class com.android.hoststubgen.test.tinyframework.subclasstest.C1 stub
-class com.android.hoststubgen.test.tinyframework.subclasstest.C2 stub
-class com.android.hoststubgen.test.tinyframework.subclasstest.C3 stub
-class com.android.hoststubgen.test.tinyframework.subclasstest.CA stub
-class com.android.hoststubgen.test.tinyframework.subclasstest.CB stub
-class com.android.hoststubgen.test.tinyframework.subclasstest.I1 stub
-class com.android.hoststubgen.test.tinyframework.subclasstest.I2 stub
-class com.android.hoststubgen.test.tinyframework.subclasstest.I3 stub
-class com.android.hoststubgen.test.tinyframework.subclasstest.IA stub
-class com.android.hoststubgen.test.tinyframework.subclasstest.IB stub
+class com.android.hoststubgen.test.tinyframework.subclasstest.C1 keep
+class com.android.hoststubgen.test.tinyframework.subclasstest.C2 keep
+class com.android.hoststubgen.test.tinyframework.subclasstest.C3 keep
+class com.android.hoststubgen.test.tinyframework.subclasstest.CA keep
+class com.android.hoststubgen.test.tinyframework.subclasstest.CB keep
+class com.android.hoststubgen.test.tinyframework.subclasstest.I1 keep
+class com.android.hoststubgen.test.tinyframework.subclasstest.I2 keep
+class com.android.hoststubgen.test.tinyframework.subclasstest.I3 keep
+class com.android.hoststubgen.test.tinyframework.subclasstest.IA keep
+class com.android.hoststubgen.test.tinyframework.subclasstest.IB keep
# Then define inheritance based policies.
class *com.android.hoststubgen.test.tinyframework.subclasstest.C1 keep
@@ -52,15 +51,15 @@
class *com.android.hoststubgen.test.tinyframework.subclasstest.IA remove
# Test package directive
-package com.android.hoststubgen.test.tinyframework.packagetest stub
+package com.android.hoststubgen.test.tinyframework.packagetest keep
class com.android.hoststubgen.test.tinyframework.packagetest.B remove
class com.android.hoststubgen.test.tinyframework.packagetest.sub.B remove
# The following rules are the same as above
-# class com.android.hoststubgen.test.tinyframework.packagetest.A stub
-# class com.android.hoststubgen.test.tinyframework.packagetest.sub.A stub
+# class com.android.hoststubgen.test.tinyframework.packagetest.A keep
+# class com.android.hoststubgen.test.tinyframework.packagetest.sub.A keep
# Used to test method call replacement.
-class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace stubclass
+class com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace keepclass
method originalAdd (II)I @com.android.hoststubgen.test.tinyframework.TinyFrameworkMethodCallReplace$ReplaceTo.add
# Used to test method call replacement.
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh b/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh
index 872bbf8..80ebf3a 100755
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/run-test-manually.sh
@@ -43,8 +43,7 @@
tiny_framework_classes=$out/tiny-framework/classes/
tiny_framework_jar=$out/tiny-framework.jar
-tiny_framework_host_stub_jar=$out/tiny-framework_host_stub.jar
-tiny_framework_host_impl_jar=$out/tiny-framework_host_impl.jar
+tiny_framework_host_jar=$out/tiny-framework_host.jar
tiny_test_classes=$out/tiny-test/classes/
tiny_test_jar=$out/tiny-test.jar
@@ -87,8 +86,7 @@
run $HOSTSTUBGEN \
@../hoststubgen-standard-options.txt \
--in-jar $tiny_framework_jar \
- --out-stub-jar $tiny_framework_host_stub_jar \
- --out-impl-jar $tiny_framework_host_impl_jar \
+ --out-jar $tiny_framework_host_jar \
--policy-override-file policy-override-tiny-framework.txt \
--gen-keep-all-file out/tiny-framework_keep_all.txt \
--gen-input-dump-file out/tiny-framework_dump.txt \
@@ -97,14 +95,14 @@
$HOSTSTUBGEN_OPTS
# Extract the jar files, so we can look into them.
-extract $tiny_framework_host_stub_jar $tiny_framework_host_impl_jar
+extract $tiny_framework_host_jar
# Build the test
echo "# Building tiny-test..."
run $JAVAC \
-cp $( \
join : \
- $tiny_framework_host_stub_jar \
+ $tiny_framework_jar \
"${test_compile_classpaths[@]}" \
) \
-d $tiny_test_classes \
@@ -124,7 +122,7 @@
-cp $( \
join : \
$tiny_test_jar \
- $tiny_framework_host_impl_jar \
+ $tiny_framework_host_jar \
"${test_compile_classpaths[@]}" \
"${test_runtime_classpaths[@]}" \
) \
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.java
index 30dfc80..ed0fa26 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotations.java
@@ -18,39 +18,30 @@
import android.hosttest.annotation.HostSideTestClassLoadHook;
import android.hosttest.annotation.HostSideTestKeep;
import android.hosttest.annotation.HostSideTestRemove;
-import android.hosttest.annotation.HostSideTestStub;
import android.hosttest.annotation.HostSideTestSubstitute;
import android.hosttest.annotation.HostSideTestThrow;
/**
* Test without class-wide annotations.
*/
-@HostSideTestStub
+@HostSideTestKeep
@HostSideTestClassLoadHook(
"com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded")
public class TinyFrameworkAnnotations {
- @HostSideTestStub
+ @HostSideTestKeep
public TinyFrameworkAnnotations() {
}
- @HostSideTestStub
- public int stub = 1;
-
@HostSideTestKeep
- public int keep = 2;
+ public int keep = 1;
// Members will be deleted by default.
// Deleted fields cannot have an initial value, because otherwise .ctor will fail to set it at
// runtime.
public int remove;
- @HostSideTestStub
- public int addOne(int value) {
- return addOneInner(value);
- }
-
@HostSideTestKeep
- public int addOneInner(int value) {
+ public int addOne(int value) {
return value + 1;
}
@@ -59,7 +50,6 @@
throw new RuntimeException();
}
- @HostSideTestStub
@HostSideTestSubstitute(suffix = "_host")
public int addTwo(int value) {
throw new RuntimeException("not supported on host side");
@@ -69,7 +59,6 @@
return value + 2;
}
- @HostSideTestStub
@HostSideTestSubstitute(suffix = "_host")
public static native int nativeAddThree(int value);
@@ -82,9 +71,4 @@
public String unsupportedMethod() {
return "This value shouldn't be seen on the host side.";
}
-
- @HostSideTestStub
- public String visibleButUsesUnsupportedMethod() {
- return unsupportedMethod();
- }
}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java
deleted file mode 100644
index f530207..0000000
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkCallerCheck.java
+++ /dev/null
@@ -1,57 +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.hoststubgen.test.tinyframework;
-
-import android.hosttest.annotation.HostSideTestKeep;
-import android.hosttest.annotation.HostSideTestStub;
-import android.hosttest.annotation.HostSideTestWholeClassStub;
-
-/**
- * Used by the benchmark.
- */
-@HostSideTestWholeClassStub
-public class TinyFrameworkCallerCheck {
-
- /**
- * This method uses an inner method (which has the caller check).
- *
- * Benchmark result: 768ns
- */
- public static int getOne_withCheck() {
- return Impl.getOneKeep();
- }
-
- /**
- * This method doesn't have any caller check.
- *
- * Benchmark result: 2ns
- */
- public static int getOne_noCheck() {
- return Impl.getOneStub();
- }
-
- private static class Impl {
- @HostSideTestKeep
- public static int getOneKeep() {
- return 1;
- }
-
- @HostSideTestStub
- public static int getOneStub() {
- return 1;
- }
- }
-}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java
index 98fc634..f734790 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassLoadHook.java
@@ -15,12 +15,12 @@
*/
package com.android.hoststubgen.test.tinyframework;
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
import java.util.HashSet;
import java.util.Set;
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
public class TinyFrameworkClassLoadHook {
private TinyFrameworkClassLoadHook() {
}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.java
index a626bc9..e83163e 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotations.java
@@ -15,16 +15,20 @@
*/
package com.android.hoststubgen.test.tinyframework;
+import android.hosttest.annotation.HostSideTestRemove;
import android.hosttest.annotation.HostSideTestSubstitute;
import android.hosttest.annotation.HostSideTestThrow;
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
public class TinyFrameworkClassWideAnnotations {
public TinyFrameworkClassWideAnnotations() {
}
- public int stub = 1;
+ public int keep = 1;
+
+ @HostSideTestRemove
+ public int remove;
public int addOne(int value) {
return value + 1;
@@ -39,12 +43,13 @@
return value + 2;
}
+ @HostSideTestRemove
+ public void toBeRemoved(String foo) {
+ throw new RuntimeException();
+ }
+
@HostSideTestThrow
public String unsupportedMethod() {
return "This value shouldn't be seen on the host side.";
}
-
- public String visibleButUsesUnsupportedMethod() {
- return unsupportedMethod();
- }
}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.java
index 8324ed9..3df21d9 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerDefault.java
@@ -15,18 +15,16 @@
*/
package com.android.hoststubgen.test.tinyframework;
-import android.hosttest.annotation.HostSideTestClassLoadHook;
-import android.hosttest.annotation.HostSideTestStub;
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestKeep;
-@HostSideTestStub
+@HostSideTestKeep
public class TinyFrameworkClassWithInitializerDefault {
static {
sInitialized = true;
}
- @HostSideTestStub
+ @HostSideTestKeep
public static boolean sInitialized;
- @HostSideTestStub
+ @HostSideTestKeep
public static Object sObject = new Object();
}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.java
index ea1ad93..cc665de 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWithInitializerStub.java
@@ -16,20 +16,20 @@
package com.android.hoststubgen.test.tinyframework;
import android.hosttest.annotation.HostSideTestClassLoadHook;
+import android.hosttest.annotation.HostSideTestKeep;
import android.hosttest.annotation.HostSideTestStaticInitializerKeep;
-import android.hosttest.annotation.HostSideTestStub;
@HostSideTestClassLoadHook(
"com.android.hoststubgen.test.tinyframework.TinyFrameworkClassLoadHook.onClassLoaded")
-@HostSideTestStub
+@HostSideTestKeep
@HostSideTestStaticInitializerKeep
public class TinyFrameworkClassWithInitializerStub {
static {
sInitialized = true;
}
- @HostSideTestStub
+ @HostSideTestKeep
public static boolean sInitialized;
- @HostSideTestStub
+ @HostSideTestKeep
public static Object sObject = new Object();
}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.java
index 51f4818..f833ad8 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumComplex.java
@@ -16,15 +16,14 @@
package com.android.hoststubgen.test.tinyframework;
import android.hosttest.annotation.HostSideTestKeep;
-import android.hosttest.annotation.HostSideTestStub;
-@HostSideTestStub
+@HostSideTestKeep
public enum TinyFrameworkEnumComplex {
- @HostSideTestStub
+ @HostSideTestKeep
RED("Red", "R"),
- @HostSideTestStub
+ @HostSideTestKeep
GREEN("Green", "G"),
- @HostSideTestStub
+ @HostSideTestKeep
BLUE("Blue", "B");
@HostSideTestKeep
@@ -33,18 +32,18 @@
@HostSideTestKeep
private final String mShortName;
- @HostSideTestStub
+ @HostSideTestKeep
TinyFrameworkEnumComplex(String longName, String shortName) {
mLongName = longName;
mShortName = shortName;
}
- @HostSideTestStub
+ @HostSideTestKeep
public String getLongName() {
return mLongName;
}
- @HostSideTestStub
+ @HostSideTestKeep
public String getShortName() {
return mShortName;
}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.java
index f440d86..c023169 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkEnumSimple.java
@@ -15,12 +15,12 @@
*/
package com.android.hoststubgen.test.tinyframework;
-import android.hosttest.annotation.HostSideTestStub;
+import android.hosttest.annotation.HostSideTestKeep;
-@HostSideTestStub
+@HostSideTestKeep
public enum TinyFrameworkEnumSimple {
- @HostSideTestStub
+ @HostSideTestKeep
CAT,
- @HostSideTestStub
+ @HostSideTestKeep
DOG,
}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java
index 909d3b4..f7cae7d 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkExceptionTester.java
@@ -15,9 +15,9 @@
*/
package com.android.hoststubgen.test.tinyframework;
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
public class TinyFrameworkExceptionTester {
public static int testException() {
try {
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java
index 1977c90..ec1efba 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkForTextPolicy.java
@@ -24,17 +24,11 @@
public int stub = 1;
- public int keep = 2;
-
// Removed fields cannot have an initial value, because otherwise .ctor will fail to set it at
// runtime.
public int remove;
public int addOne(int value) {
- return addOneInner(value);
- }
-
- public int addOneInner(int value) {
return value + 1;
}
@@ -95,8 +89,4 @@
public String unsupportedMethod() {
return "This value shouldn't be seen on the host side.";
}
-
- public String visibleButUsesUnsupportedMethod() {
- return unsupportedMethod();
- }
}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.java
index 0d1203b..1ca653e 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkLambdas.java
@@ -15,8 +15,8 @@
*/
package com.android.hoststubgen.test.tinyframework;
+import android.hosttest.annotation.HostSideTestKeep;
import android.hosttest.annotation.HostSideTestStaticInitializerKeep;
-import android.hosttest.annotation.HostSideTestStub;
import java.util.function.Supplier;
@@ -28,48 +28,48 @@
*
* Implicit filter should take care of them.
*/
-@HostSideTestStub
+@HostSideTestKeep
@HostSideTestStaticInitializerKeep
public class TinyFrameworkLambdas {
- @HostSideTestStub
+ @HostSideTestKeep
public TinyFrameworkLambdas() {
}
- @HostSideTestStub
+ @HostSideTestKeep
public final Supplier<Integer> mSupplier = () -> 1;
- @HostSideTestStub
+ @HostSideTestKeep
public static final Supplier<Integer> sSupplier = () -> 2;
- @HostSideTestStub
+ @HostSideTestKeep
public Supplier<Integer> getSupplier() {
return () -> 3;
}
- @HostSideTestStub
+ @HostSideTestKeep
public static Supplier<Integer> getSupplier_static() {
return () -> 4;
}
- @HostSideTestStub
+ @HostSideTestKeep
@HostSideTestStaticInitializerKeep
public static class Nested {
- @HostSideTestStub
+ @HostSideTestKeep
public Nested() {
}
- @HostSideTestStub
+ @HostSideTestKeep
public final Supplier<Integer> mSupplier = () -> 5;
- @HostSideTestStub
+ @HostSideTestKeep
public static final Supplier<Integer> sSupplier = () -> 6;
- @HostSideTestStub
+ @HostSideTestKeep
public Supplier<Integer> getSupplier() {
return () -> 7;
}
- @HostSideTestStub
+ @HostSideTestKeep
public static Supplier<Integer> getSupplier_static() {
return () -> 8;
}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java
index 1ff3744..57c69a3 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkMethodCallReplace.java
@@ -15,11 +15,11 @@
*/
package com.android.hoststubgen.test.tinyframework;
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
import java.util.concurrent.atomic.AtomicBoolean;
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
public class TinyFrameworkMethodCallReplace {
// This method should return true.
public static boolean nonStaticMethodCallReplaceTester() throws Exception {
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java
index 09ee183..04a551c 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative.java
@@ -15,19 +15,23 @@
*/
package com.android.hoststubgen.test.tinyframework;
-import android.hosttest.annotation.HostSideTestNativeSubstitutionClass;
+import android.hosttest.annotation.HostSideTestRedirect;
+import android.hosttest.annotation.HostSideTestRedirectionClass;
import android.hosttest.annotation.HostSideTestThrow;
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
-@HostSideTestWholeClassStub
-@HostSideTestNativeSubstitutionClass("TinyFrameworkNative_host")
+@HostSideTestWholeClassKeep
+@HostSideTestRedirectionClass("TinyFrameworkNative_host")
public class TinyFrameworkNative {
+
+ @HostSideTestRedirect
public static native int nativeAddTwo(int arg);
public static int nativeAddTwo_should_be_like_this(int arg) {
return TinyFrameworkNative_host.nativeAddTwo(arg);
}
+ @HostSideTestRedirect
public static native long nativeLongPlus(long arg1, long arg2);
public static long nativeLongPlus_should_be_like_this(long arg1, long arg2) {
@@ -40,6 +44,7 @@
this.value = v;
}
+ @HostSideTestRedirect
public native int nativeNonStaticAddToValue(int arg);
public int nativeNonStaticAddToValue_should_be_like_this(int arg) {
@@ -49,9 +54,22 @@
@HostSideTestThrow
public static native void nativeStillNotSupported();
+ public static native void nativeStillKeep();
+
public static void nativeStillNotSupported_should_be_like_this() {
throw new RuntimeException();
}
+ @HostSideTestRedirect
public static native byte nativeBytePlus(byte arg1, byte arg2);
+
+ @HostSideTestRedirect
+ public void notNativeRedirected() {
+ throw new RuntimeException();
+ }
+
+ @HostSideTestRedirect
+ public static void notNativeStaticRedirected() {
+ throw new RuntimeException();
+ }
}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java
index b23c216..c7a29a1 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNative_host.java
@@ -17,8 +17,6 @@
import android.hosttest.annotation.HostSideTestWholeClassKeep;
-// TODO: This annotation shouldn't be needed.
-// We should infer it from HostSideTestNativeSubstitutionClass.
@HostSideTestWholeClassKeep
public class TinyFrameworkNative_host {
public static int nativeAddTwo(int arg) {
@@ -38,4 +36,10 @@
public static byte nativeBytePlus(byte arg1, byte arg2) {
return (byte) (arg1 + arg2);
}
+
+ public static void notNativeRedirected(TinyFrameworkNative source) {
+ }
+
+ public static void notNativeStaticRedirected() {
+ }
}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java
index fec307a..c1ea2ee 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkNestedClasses.java
@@ -15,11 +15,11 @@
*/
package com.android.hoststubgen.test.tinyframework;
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
import java.util.function.Supplier;
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
public class TinyFrameworkNestedClasses {
public final Supplier<Integer> mSupplier = new Supplier<Integer>() {
@Override
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.java
index a82be54..941fcff 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkPackageRedirect.java
@@ -15,9 +15,9 @@
*/
package com.android.hoststubgen.test.tinyframework;
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
public class TinyFrameworkPackageRedirect {
/**
* A method that uses "unsupported" class. HostStubGen will redirect them to the "supported"
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.java
index 31a164a..707bc0e 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkRenamedClassCaller.java
@@ -15,9 +15,9 @@
*/
package com.android.hoststubgen.test.tinyframework;
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
public class TinyFrameworkRenamedClassCaller {
/** Calls the class that'll be renamed. */
public static int foo(int value) {
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.java
index 1430bcb..8319ced 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkToBeRenamed.java
@@ -15,12 +15,12 @@
*/
package com.android.hoststubgen.test.tinyframework;
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
/**
* This class will be renamed by the "rename" directive in the policy file.
*/
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
public class TinyFrameworkToBeRenamed {
private final int mValue;
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/unsupported/UnsupportedClass.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/unsupported/UnsupportedClass.java
index 0409b02..92f41ac 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/unsupported/UnsupportedClass.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-framework/src/com/unsupported/UnsupportedClass.java
@@ -15,10 +15,10 @@
*/
package com.unsupported;
-import android.hosttest.annotation.HostSideTestWholeClassStub;
+import android.hosttest.annotation.HostSideTestWholeClassKeep;
// Used for testing --package-redirect.
-@HostSideTestWholeClassStub
+@HostSideTestWholeClassKeep
public class UnsupportedClass {
public UnsupportedClass(int value) {
throw new RuntimeException("This class is not supported");
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/LargeTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/LargeTest.java
deleted file mode 100644
index 76bbcad..0000000
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/LargeTest.java
+++ /dev/null
@@ -1,28 +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.hoststubgen.test.tinyframework;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * We don't want to use any android classes in this module, so we create our own copy of it here.
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD, ElementType.TYPE})
-public @interface LargeTest {}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotationsTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotationsTest.java
index 181902a..1ae0493 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotationsTest.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkAnnotationsTest.java
@@ -17,6 +17,8 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
+
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -29,19 +31,15 @@
public void testSimple() {
TinyFrameworkAnnotations tfc = new TinyFrameworkAnnotations();
assertThat(tfc.addOne(1)).isEqualTo(2);
- assertThat(tfc.stub).isEqualTo(1);
+ assertThat(tfc.keep).isEqualTo(1);
}
-// @Test
-// public void testDoesntCompile() {
-// TinyFrameworkAnnotations tfc = new TinyFrameworkAnnotations();
-//
-// tfc.addOneInner(1); // Shouldn't compile.
-// tfc.toBeRemoved("abc"); // Shouldn't compile.
-// tfc.unsupportedMethod(); // Shouldn't compile.
-// int a = tfc.keep; // Shouldn't compile
-// int b = tfc.remove; // Shouldn't compile
-// }
+ @Test
+ public void testRemove() {
+ TinyFrameworkAnnotations tfc = new TinyFrameworkAnnotations();
+ assertThrows(NoSuchMethodError.class, () -> tfc.toBeRemoved("abc"));
+ assertThrows(NoSuchFieldError.class, () -> tfc.remove = 1);
+ }
@Test
public void testSubstitute() {
@@ -56,11 +54,11 @@
}
@Test
- public void testVisibleButUsesUnsupportedMethod() {
+ public void testUnsupportedMethod() {
TinyFrameworkAnnotations tfc = new TinyFrameworkAnnotations();
thrown.expect(RuntimeException.class);
thrown.expectMessage("not yet supported");
- tfc.visibleButUsesUnsupportedMethod();
+ tfc.unsupportedMethod();
}
}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java
deleted file mode 100644
index d57735b..0000000
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkBenchmark.java
+++ /dev/null
@@ -1,71 +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.hoststubgen.test.tinyframework;
-
-import org.junit.Test;
-
-import java.text.DecimalFormat;
-
-/**
- * Contains simple micro-benchmarks.
- */
-@LargeTest
-public class TinyFrameworkBenchmark {
- private static final int MINIMAL_ITERATION = 1000;
- private static final int MEASURE_SECONDS = 1;
-
- private static final DecimalFormat sFormatter = new DecimalFormat("#,###");
-
- private void doBenchmark(String name, Runnable r) {
- // Worm up
- for (int i = 0; i < MINIMAL_ITERATION; i++) {
- r.run();
- }
-
- // Start measuring.
- final long start = System.nanoTime();
- final long end = start + MEASURE_SECONDS * 1_000_000_000L;
-
- double iteration = 0;
- while (System.nanoTime() <= end) {
- for (int i = 0; i < MINIMAL_ITERATION; i++) {
- r.run();
- }
- iteration += MINIMAL_ITERATION;
- }
-
- final long realEnd = System.nanoTime();
-
- System.out.println(String.format("%s\t%s", name,
- sFormatter.format((((double) realEnd - start)) / iteration)));
- }
-
- /**
- * Micro-benchmark for a method without a non-stub caller check.
- */
- @Test
- public void benchNoCallerCheck() {
- doBenchmark("No caller check", TinyFrameworkCallerCheck::getOne_noCheck);
- }
-
- /**
- * Micro-benchmark for a method with a non-stub caller check.
- */
- @Test
- public void benchWithCallerCheck() {
- doBenchmark("With caller check", TinyFrameworkCallerCheck::getOne_withCheck);
- }
-}
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
index dda5a05..68673dc 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassTest.java
@@ -17,7 +17,7 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThrows;
import com.android.hoststubgen.test.tinyframework.R.Nested;
@@ -40,16 +40,12 @@
assertThat(tfc.stub).isEqualTo(1);
}
-// @Test
-// public void testDoesntCompile() {
-// TinyFrameworkClass tfc = new TinyFrameworkClass();
-//
-// tfc.addOneInner(1); // Shouldn't compile.
-// tfc.toBeRemoved("abc"); // Shouldn't compile.
-// tfc.unsupportedMethod(); // Shouldn't compile.
-// int a = tfc.keep; // Shouldn't compile
-// int b = tfc.remove; // Shouldn't compile
-// }
+ @Test
+ public void testRemove() {
+ TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy();
+ assertThrows(NoSuchMethodError.class, () -> tfc.toBeRemoved("abc"));
+ assertThrows(NoSuchFieldError.class, () -> tfc.remove = 1);
+ }
@Test
public void testIgnore() {
@@ -78,12 +74,12 @@
}
@Test
- public void testVisibleButUsesUnsupportedMethod() {
+ public void testUnsupportedMethod() {
TinyFrameworkForTextPolicy tfc = new TinyFrameworkForTextPolicy();
thrown.expect(RuntimeException.class);
thrown.expectMessage("not yet supported");
- tfc.visibleButUsesUnsupportedMethod();
+ tfc.unsupportedMethod();
}
@Test
@@ -149,28 +145,28 @@
}
@Test
- public void testSubstituteNativeWithThrow() throws Exception {
- // We can't use TinyFrameworkNative.nativeStillNotSupported() directly in this class,
- // because @Throw implies @Keep (not @Stub), and we currently compile this test
- // against the stub jar (so it won't contain @Throw methods).
- //
- // But the method exists at runtime, so we can use reflections to call it.
- //
- // In the real Ravenwood environment, we don't use HostStubGen's stub jar at all,
- // so it's not a problem.
+ public void testSubstituteNativeWithThrow() {
+ thrown.expect(RuntimeException.class);
+ thrown.expectMessage("not yet supported");
- final var clazz = TinyFrameworkNative.class;
- final var method = clazz.getMethod("nativeStillNotSupported");
+ TinyFrameworkNative.nativeStillNotSupported();
+ }
- try {
- method.invoke(null);
+ @Test
+ public void testSubstituteNativeWithKeep() {
+ // We don't want to complicate the test by setting up JNI,
+ // so to test out whether the native method is preserved, we
+ // check whether calling it will throw UnsatisfiedLinkError,
+ // which would only happen on native methods.
+ thrown.expect(UnsatisfiedLinkError.class);
- fail("java.lang.reflect.InvocationTargetException expected");
+ TinyFrameworkNative.nativeStillKeep();
+ }
- } catch (java.lang.reflect.InvocationTargetException e) {
- var inner = e.getCause();
- assertThat(inner.getMessage()).contains("not yet supported");
- }
+ @Test
+ public void testNotNativeRedirect() {
+ TinyFrameworkNative.notNativeStaticRedirected();
+ new TinyFrameworkNative().notNativeRedirected();
}
@Test
@@ -179,7 +175,6 @@
thrown.expectMessage("Outer exception");
TinyFrameworkExceptionTester.testException();
-
}
@Test
diff --git a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotationsTest.java b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotationsTest.java
index 83753b5..34c98e9 100644
--- a/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotationsTest.java
+++ b/tools/hoststubgen/hoststubgen/test-tiny-framework/tiny-test/src/com/android/hoststubgen/test/tinyframework/TinyFrameworkClassWideAnnotationsTest.java
@@ -17,6 +17,8 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
+
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -29,7 +31,14 @@
public void testSimple() {
var tfc = new TinyFrameworkClassWideAnnotations();
assertThat(tfc.addOne(1)).isEqualTo(2);
- assertThat(tfc.stub).isEqualTo(1);
+ assertThat(tfc.keep).isEqualTo(1);
+ }
+
+ @Test
+ public void testRemove() {
+ var tfc = new TinyFrameworkClassWideAnnotations();
+ assertThrows(NoSuchMethodError.class, () -> tfc.toBeRemoved("abc"));
+ assertThrows(NoSuchFieldError.class, () -> tfc.remove = 1);
}
@Test
@@ -39,12 +48,12 @@
}
@Test
- public void testVisibleButUsesUnsupportedMethod() {
+ public void testUnsupportedMethod() {
var tfc = new TinyFrameworkClassWideAnnotations();
thrown.expect(RuntimeException.class);
thrown.expectMessage("not yet supported");
- tfc.visibleButUsesUnsupportedMethod();
+ tfc.unsupportedMethod();
}
@Test
diff --git a/tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/utils/ClassFilterTest.kt b/tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/utils/ClassFilterTest.kt
index f651514..85b6e80 100644
--- a/tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/utils/ClassFilterTest.kt
+++ b/tools/hoststubgen/hoststubgen/test/com/android/hoststubgen/utils/ClassFilterTest.kt
@@ -72,6 +72,18 @@
}
@Test
+ fun testNestedClass() {
+ val f = ClassFilter.buildFromString("a.b.c\nm.n.o\$p\n", false, "X")
+ assertThat(f.matches("a/b/c")).isEqualTo(true)
+ assertThat(f.matches("a/b/c\$d")).isEqualTo(true)
+ assertThat(f.matches("a/b/c\$d\$e")).isEqualTo(true)
+ assertThat(f.matches("m/n/o")).isEqualTo(false)
+ assertThat(f.matches("m/n/o\$p")).isEqualTo(true)
+ assertThat(f.matches("m/n/o\$p\$r")).isEqualTo(true)
+ assertThat(f.matches("m/n/o\$p\$r\$")).isEqualTo(true)
+ }
+
+ @Test
fun testBadFilter1() {
try {
ClassFilter.buildFromString("""
diff --git a/tools/lint/common/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt b/tools/lint/common/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt
index 24d203f..f5af99e 100644
--- a/tools/lint/common/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt
+++ b/tools/lint/common/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt
@@ -24,20 +24,31 @@
import org.jetbrains.uast.UMethod
/**
- * Given a UMethod, determine if this method is the entrypoint to an interface
- * generated by AIDL, returning the interface name if so, otherwise returning
- * null
+ * Given a UMethod, determine if this method is the entrypoint to an interface generated by AIDL,
+ * returning the interface name if so, otherwise returning null.
*/
fun getContainingAidlInterface(context: JavaContext, node: UMethod): String? {
+ return containingAidlInterfacePsiClass(context, node)?.name
+}
+
+/**
+ * Given a UMethod, determine if this method is the entrypoint to an interface generated by AIDL,
+ * returning the fully qualified interface name if so, otherwise returning null.
+ */
+fun getContainingAidlInterfaceQualified(context: JavaContext, node: UMethod): String? {
+ return containingAidlInterfacePsiClass(context, node)?.qualifiedName
+}
+
+private fun containingAidlInterfacePsiClass(context: JavaContext, node: UMethod): PsiClass? {
val containingStub = containingStub(context, node) ?: return null
val superMethod = node.findSuperMethods(containingStub)
if (superMethod.isEmpty()) return null
- return containingStub.containingClass?.name
+ return containingStub.containingClass
}
-/* Returns the containing Stub class if any. This is not sufficient to infer
- * that the method itself extends an AIDL generated method. See
- * getContainingAidlInterface for that purpose.
+/**
+ * Returns the containing Stub class if any. This is not sufficient to infer that the method itself
+ * extends an AIDL generated method. See getContainingAidlInterface for that purpose.
*/
fun containingStub(context: JavaContext, node: UMethod?): PsiClass? {
var superClass = node?.containingClass?.superClass
@@ -48,7 +59,7 @@
return null
}
-private fun isStub(context: JavaContext, psiClass: PsiClass?): Boolean {
+fun isStub(context: JavaContext, psiClass: PsiClass?): Boolean {
if (psiClass == null) return false
if (psiClass.name != "Stub") return false
if (!context.evaluator.isStatic(psiClass)) return false
diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/ExemptAidlInterfaces.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/ExemptAidlInterfaces.kt
new file mode 100644
index 0000000..8777712
--- /dev/null
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/ExemptAidlInterfaces.kt
@@ -0,0 +1,774 @@
+/*
+ * 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.google.android.lint.aidl
+
+/**
+ * The exemptAidlInterfaces set was generated by running ExemptAidlInterfacesGenerator on the
+ * entire source tree. To reproduce the results, run generate-exempt-aidl-interfaces.sh
+ * located in tools/lint/utils.
+ *
+ * TODO: b/363248121 - Use the exemptAidlInterfaces set inside PermissionAnnotationDetector when it
+ * gets migrated to a global lint check.
+ */
+val exemptAidlInterfaces = setOf(
+ "android.accessibilityservice.IAccessibilityServiceConnection",
+ "android.accessibilityservice.IBrailleDisplayConnection",
+ "android.accounts.IAccountAuthenticatorResponse",
+ "android.accounts.IAccountManager",
+ "android.accounts.IAccountManagerResponse",
+ "android.adservices.adid.IAdIdProviderService",
+ "android.adservices.adid.IAdIdService",
+ "android.adservices.adid.IGetAdIdCallback",
+ "android.adservices.adid.IGetAdIdProviderCallback",
+ "android.adservices.adselection.AdSelectionCallback",
+ "android.adservices.adselection.AdSelectionOverrideCallback",
+ "android.adservices.adselection.AdSelectionService",
+ "android.adservices.adselection.GetAdSelectionDataCallback",
+ "android.adservices.adselection.PersistAdSelectionResultCallback",
+ "android.adservices.adselection.ReportImpressionCallback",
+ "android.adservices.adselection.ReportInteractionCallback",
+ "android.adservices.adselection.SetAppInstallAdvertisersCallback",
+ "android.adservices.adselection.UpdateAdCounterHistogramCallback",
+ "android.adservices.appsetid.IAppSetIdProviderService",
+ "android.adservices.appsetid.IAppSetIdService",
+ "android.adservices.appsetid.IGetAppSetIdCallback",
+ "android.adservices.appsetid.IGetAppSetIdProviderCallback",
+ "android.adservices.cobalt.IAdServicesCobaltUploadService",
+ "android.adservices.common.IAdServicesCommonCallback",
+ "android.adservices.common.IAdServicesCommonService",
+ "android.adservices.common.IAdServicesCommonStatesCallback",
+ "android.adservices.common.IEnableAdServicesCallback",
+ "android.adservices.common.IUpdateAdIdCallback",
+ "android.adservices.customaudience.CustomAudienceOverrideCallback",
+ "android.adservices.customaudience.FetchAndJoinCustomAudienceCallback",
+ "android.adservices.customaudience.ICustomAudienceCallback",
+ "android.adservices.customaudience.ICustomAudienceService",
+ "android.adservices.customaudience.ScheduleCustomAudienceUpdateCallback",
+ "android.adservices.extdata.IAdServicesExtDataStorageService",
+ "android.adservices.extdata.IGetAdServicesExtDataCallback",
+ "android.adservices.measurement.IMeasurementApiStatusCallback",
+ "android.adservices.measurement.IMeasurementCallback",
+ "android.adservices.measurement.IMeasurementService",
+ "android.adservices.ondevicepersonalization.aidl.IDataAccessService",
+ "android.adservices.ondevicepersonalization.aidl.IDataAccessServiceCallback",
+ "android.adservices.ondevicepersonalization.aidl.IExecuteCallback",
+ "android.adservices.ondevicepersonalization.aidl.IFederatedComputeCallback",
+ "android.adservices.ondevicepersonalization.aidl.IFederatedComputeService",
+ "android.adservices.ondevicepersonalization.aidl.IIsolatedModelService",
+ "android.adservices.ondevicepersonalization.aidl.IIsolatedModelServiceCallback",
+ "android.adservices.ondevicepersonalization.aidl.IIsolatedService",
+ "android.adservices.ondevicepersonalization.aidl.IIsolatedServiceCallback",
+ "android.adservices.ondevicepersonalization.aidl.IOnDevicePersonalizationConfigService",
+ "android.adservices.ondevicepersonalization.aidl.IOnDevicePersonalizationConfigServiceCallback",
+ "android.adservices.ondevicepersonalization.aidl.IOnDevicePersonalizationDebugService",
+ "android.adservices.ondevicepersonalization.aidl.IOnDevicePersonalizationManagingService",
+ "android.adservices.ondevicepersonalization.aidl.IRegisterMeasurementEventCallback",
+ "android.adservices.ondevicepersonalization.aidl.IRequestSurfacePackageCallback",
+ "android.adservices.shell.IShellCommand",
+ "android.adservices.shell.IShellCommandCallback",
+ "android.adservices.signals.IProtectedSignalsService",
+ "android.adservices.signals.UpdateSignalsCallback",
+ "android.adservices.topics.IGetTopicsCallback",
+ "android.adservices.topics.ITopicsService",
+ "android.app.admin.IDevicePolicyManager",
+ "android.app.adservices.IAdServicesManager",
+ "android.app.ambientcontext.IAmbientContextManager",
+ "android.app.ambientcontext.IAmbientContextObserver",
+ "android.app.appsearch.aidl.IAppFunctionService",
+ "android.app.appsearch.aidl.IAppSearchBatchResultCallback",
+ "android.app.appsearch.aidl.IAppSearchManager",
+ "android.app.appsearch.aidl.IAppSearchObserverProxy",
+ "android.app.appsearch.aidl.IAppSearchResultCallback",
+ "android.app.backup.IBackupCallback",
+ "android.app.backup.IBackupManager",
+ "android.app.backup.IRestoreSession",
+ "android.app.blob.IBlobCommitCallback",
+ "android.app.blob.IBlobStoreManager",
+ "android.app.blob.IBlobStoreSession",
+ "android.app.contentsuggestions.IContentSuggestionsManager",
+ "android.app.contextualsearch.IContextualSearchManager",
+ "android.app.ecm.IEnhancedConfirmationManager",
+ "android.apphibernation.IAppHibernationService",
+ "android.app.IActivityClientController",
+ "android.app.IActivityController",
+ "android.app.IActivityTaskManager",
+ "android.app.IAlarmCompleteListener",
+ "android.app.IAlarmListener",
+ "android.app.IAlarmManager",
+ "android.app.IApplicationThread",
+ "android.app.IAppTask",
+ "android.app.IAppTraceRetriever",
+ "android.app.IAssistDataReceiver",
+ "android.app.IForegroundServiceObserver",
+ "android.app.IGameManagerService",
+ "android.app.IGrammaticalInflectionManager",
+ "android.app.ILocaleManager",
+ "android.app.INotificationManager",
+ "android.app.IParcelFileDescriptorRetriever",
+ "android.app.IProcessObserver",
+ "android.app.ISearchManager",
+ "android.app.IStopUserCallback",
+ "android.app.ITaskStackListener",
+ "android.app.IUiModeManager",
+ "android.app.IUriGrantsManager",
+ "android.app.IUserSwitchObserver",
+ "android.app.IWallpaperManager",
+ "android.app.job.IJobCallback",
+ "android.app.job.IJobScheduler",
+ "android.app.job.IJobService",
+ "android.app.ondeviceintelligence.IDownloadCallback",
+ "android.app.ondeviceintelligence.IFeatureCallback",
+ "android.app.ondeviceintelligence.IFeatureDetailsCallback",
+ "android.app.ondeviceintelligence.IListFeaturesCallback",
+ "android.app.ondeviceintelligence.IOnDeviceIntelligenceManager",
+ "android.app.ondeviceintelligence.IProcessingSignal",
+ "android.app.ondeviceintelligence.IResponseCallback",
+ "android.app.ondeviceintelligence.IStreamingResponseCallback",
+ "android.app.ondeviceintelligence.ITokenInfoCallback",
+ "android.app.people.IPeopleManager",
+ "android.app.pinner.IPinnerService",
+ "android.app.prediction.IPredictionManager",
+ "android.app.role.IOnRoleHoldersChangedListener",
+ "android.app.role.IRoleController",
+ "android.app.role.IRoleManager",
+ "android.app.sdksandbox.ILoadSdkCallback",
+ "android.app.sdksandbox.IRequestSurfacePackageCallback",
+ "android.app.sdksandbox.ISdkSandboxManager",
+ "android.app.sdksandbox.ISdkSandboxProcessDeathCallback",
+ "android.app.sdksandbox.ISdkToServiceCallback",
+ "android.app.sdksandbox.ISharedPreferencesSyncCallback",
+ "android.app.sdksandbox.IUnloadSdkCallback",
+ "android.app.sdksandbox.testutils.testscenario.ISdkSandboxTestExecutor",
+ "android.app.search.ISearchUiManager",
+ "android.app.slice.ISliceManager",
+ "android.app.smartspace.ISmartspaceManager",
+ "android.app.timedetector.ITimeDetectorService",
+ "android.app.timezonedetector.ITimeZoneDetectorService",
+ "android.app.trust.ITrustManager",
+ "android.app.usage.IStorageStatsManager",
+ "android.app.usage.IUsageStatsManager",
+ "android.app.wallpapereffectsgeneration.IWallpaperEffectsGenerationManager",
+ "android.app.wearable.IWearableSensingCallback",
+ "android.app.wearable.IWearableSensingManager",
+ "android.bluetooth.IBluetooth",
+ "android.bluetooth.IBluetoothA2dp",
+ "android.bluetooth.IBluetoothA2dpSink",
+ "android.bluetooth.IBluetoothActivityEnergyInfoListener",
+ "android.bluetooth.IBluetoothAvrcpController",
+ "android.bluetooth.IBluetoothCallback",
+ "android.bluetooth.IBluetoothConnectionCallback",
+ "android.bluetooth.IBluetoothCsipSetCoordinator",
+ "android.bluetooth.IBluetoothCsipSetCoordinatorLockCallback",
+ "android.bluetooth.IBluetoothGatt",
+ "android.bluetooth.IBluetoothGattCallback",
+ "android.bluetooth.IBluetoothGattServerCallback",
+ "android.bluetooth.IBluetoothHapClient",
+ "android.bluetooth.IBluetoothHapClientCallback",
+ "android.bluetooth.IBluetoothHeadset",
+ "android.bluetooth.IBluetoothHeadsetClient",
+ "android.bluetooth.IBluetoothHearingAid",
+ "android.bluetooth.IBluetoothHidDevice",
+ "android.bluetooth.IBluetoothHidDeviceCallback",
+ "android.bluetooth.IBluetoothHidHost",
+ "android.bluetooth.IBluetoothLeAudio",
+ "android.bluetooth.IBluetoothLeAudioCallback",
+ "android.bluetooth.IBluetoothLeBroadcastAssistant",
+ "android.bluetooth.IBluetoothLeBroadcastAssistantCallback",
+ "android.bluetooth.IBluetoothLeBroadcastCallback",
+ "android.bluetooth.IBluetoothLeCallControl",
+ "android.bluetooth.IBluetoothLeCallControlCallback",
+ "android.bluetooth.IBluetoothManager",
+ "android.bluetooth.IBluetoothManagerCallback",
+ "android.bluetooth.IBluetoothMap",
+ "android.bluetooth.IBluetoothMapClient",
+ "android.bluetooth.IBluetoothMcpServiceManager",
+ "android.bluetooth.IBluetoothMetadataListener",
+ "android.bluetooth.IBluetoothOobDataCallback",
+ "android.bluetooth.IBluetoothPan",
+ "android.bluetooth.IBluetoothPanCallback",
+ "android.bluetooth.IBluetoothPbap",
+ "android.bluetooth.IBluetoothPbapClient",
+ "android.bluetooth.IBluetoothPreferredAudioProfilesCallback",
+ "android.bluetooth.IBluetoothQualityReportReadyCallback",
+ "android.bluetooth.IBluetoothSap",
+ "android.bluetooth.IBluetoothScan",
+ "android.bluetooth.IBluetoothSocketManager",
+ "android.bluetooth.IBluetoothVolumeControl",
+ "android.bluetooth.IBluetoothVolumeControlCallback",
+ "android.bluetooth.le.IAdvertisingSetCallback",
+ "android.bluetooth.le.IDistanceMeasurementCallback",
+ "android.bluetooth.le.IPeriodicAdvertisingCallback",
+ "android.bluetooth.le.IScannerCallback",
+ "android.companion.ICompanionDeviceManager",
+ "android.companion.IOnMessageReceivedListener",
+ "android.companion.IOnTransportsChangedListener",
+ "android.companion.virtualcamera.IVirtualCameraCallback",
+ "android.companion.virtual.IVirtualDevice",
+ "android.companion.virtual.IVirtualDeviceManager",
+ "android.companion.virtualnative.IVirtualDeviceManagerNative",
+ "android.content.IClipboard",
+ "android.content.IContentService",
+ "android.content.IIntentReceiver",
+ "android.content.IIntentSender",
+ "android.content.integrity.IAppIntegrityManager",
+ "android.content.IRestrictionsManager",
+ "android.content.ISyncAdapterUnsyncableAccountCallback",
+ "android.content.ISyncContext",
+ "android.content.om.IOverlayManager",
+ "android.content.pm.dex.IArtManager",
+ "android.content.pm.dex.ISnapshotRuntimeProfileCallback",
+ "android.content.pm.IBackgroundInstallControlService",
+ "android.content.pm.ICrossProfileApps",
+ "android.content.pm.IDataLoaderManager",
+ "android.content.pm.IDataLoaderStatusListener",
+ "android.content.pm.ILauncherApps",
+ "android.content.pm.IOnChecksumsReadyListener",
+ "android.content.pm.IOtaDexopt",
+ "android.content.pm.IPackageDataObserver",
+ "android.content.pm.IPackageDeleteObserver",
+ "android.content.pm.IPackageInstaller",
+ "android.content.pm.IPackageInstallerSession",
+ "android.content.pm.IPackageInstallerSessionFileSystemConnector",
+ "android.content.pm.IPackageInstallObserver2",
+ "android.content.pm.IPackageLoadingProgressCallback",
+ "android.content.pm.IPackageManager",
+ "android.content.pm.IPackageManagerNative",
+ "android.content.pm.IPackageMoveObserver",
+ "android.content.pm.IPinItemRequest",
+ "android.content.pm.IShortcutService",
+ "android.content.pm.IStagedApexObserver",
+ "android.content.pm.verify.domain.IDomainVerificationManager",
+ "android.content.res.IResourcesManager",
+ "android.content.rollback.IRollbackManager",
+ "android.credentials.ICredentialManager",
+ "android.debug.IAdbTransport",
+ "android.devicelock.IDeviceLockService",
+ "android.devicelock.IGetDeviceIdCallback",
+ "android.devicelock.IGetKioskAppsCallback",
+ "android.devicelock.IIsDeviceLockedCallback",
+ "android.devicelock.IVoidResultCallback",
+ "android.federatedcompute.aidl.IExampleStoreCallback",
+ "android.federatedcompute.aidl.IExampleStoreIterator",
+ "android.federatedcompute.aidl.IExampleStoreIteratorCallback",
+ "android.federatedcompute.aidl.IExampleStoreService",
+ "android.federatedcompute.aidl.IFederatedComputeCallback",
+ "android.federatedcompute.aidl.IFederatedComputeService",
+ "android.federatedcompute.aidl.IResultHandlingService",
+ "android.flags.IFeatureFlags",
+ "android.frameworks.location.altitude.IAltitudeService",
+ "android.frameworks.vibrator.IVibratorController",
+ "android.frameworks.vibrator.IVibratorControlService",
+ "android.gsi.IGsiServiceCallback",
+ "android.hardware.biometrics.AuthenticationStateListener",
+ "android.hardware.biometrics.common.ICancellationSignal",
+ "android.hardware.biometrics.face.IFace",
+ "android.hardware.biometrics.face.ISession",
+ "android.hardware.biometrics.face.ISessionCallback",
+ "android.hardware.biometrics.fingerprint.IFingerprint",
+ "android.hardware.biometrics.fingerprint.ISession",
+ "android.hardware.biometrics.fingerprint.ISessionCallback",
+ "android.hardware.biometrics.IAuthService",
+ "android.hardware.biometrics.IBiometricAuthenticator",
+ "android.hardware.biometrics.IBiometricContextListener",
+ "android.hardware.biometrics.IBiometricSensorReceiver",
+ "android.hardware.biometrics.IBiometricService",
+ "android.hardware.biometrics.IBiometricStateListener",
+ "android.hardware.biometrics.IBiometricSysuiReceiver",
+ "android.hardware.biometrics.IInvalidationCallback",
+ "android.hardware.biometrics.ITestSession",
+ "android.hardware.broadcastradio.IAnnouncementListener",
+ "android.hardware.broadcastradio.ITunerCallback",
+ "android.hardware.contexthub.IContextHubCallback",
+ "android.hardware.devicestate.IDeviceStateManager",
+ "android.hardware.display.IColorDisplayManager",
+ "android.hardware.display.IDisplayManager",
+ "android.hardware.face.IFaceAuthenticatorsRegisteredCallback",
+ "android.hardware.face.IFaceService",
+ "android.hardware.face.IFaceServiceReceiver",
+ "android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback",
+ "android.hardware.fingerprint.IFingerprintClientActiveCallback",
+ "android.hardware.fingerprint.IFingerprintService",
+ "android.hardware.fingerprint.IFingerprintServiceReceiver",
+ "android.hardware.fingerprint.IUdfpsOverlayControllerCallback",
+ "android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback",
+ "android.hardware.hdmi.IHdmiControlCallback",
+ "android.hardware.hdmi.IHdmiControlService",
+ "android.hardware.hdmi.IHdmiDeviceEventListener",
+ "android.hardware.hdmi.IHdmiHotplugEventListener",
+ "android.hardware.hdmi.IHdmiSystemAudioModeChangeListener",
+ "android.hardware.health.IHealthInfoCallback",
+ "android.hardware.ICameraServiceProxy",
+ "android.hardware.IConsumerIrService",
+ "android.hardware.input.IInputManager",
+ "android.hardware.iris.IIrisService",
+ "android.hardware.ISensorPrivacyManager",
+ "android.hardware.ISerialManager",
+ "android.hardware.lights.ILightsManager",
+ "android.hardware.location.IContextHubClient",
+ "android.hardware.location.IContextHubClientCallback",
+ "android.hardware.location.IContextHubService",
+ "android.hardware.location.IContextHubTransactionCallback",
+ "android.hardware.location.ISignificantPlaceProviderManager",
+ "android.hardware.radio.IAnnouncementListener",
+ "android.hardware.radio.ICloseHandle",
+ "android.hardware.radio.ims.media.IImsMedia",
+ "android.hardware.radio.ims.media.IImsMediaListener",
+ "android.hardware.radio.ims.media.IImsMediaSession",
+ "android.hardware.radio.ims.media.IImsMediaSessionListener",
+ "android.hardware.radio.IRadioService",
+ "android.hardware.radio.ITuner",
+ "android.hardware.radio.sap.ISapCallback",
+ "android.hardware.soundtrigger3.ISoundTriggerHw",
+ "android.hardware.soundtrigger3.ISoundTriggerHwCallback",
+ "android.hardware.soundtrigger3.ISoundTriggerHwGlobalCallback",
+ "android.hardware.soundtrigger.IRecognitionStatusCallback",
+ "android.hardware.tetheroffload.ITetheringOffloadCallback",
+ "android.hardware.thermal.IThermalChangedCallback",
+ "android.hardware.tv.hdmi.cec.IHdmiCecCallback",
+ "android.hardware.tv.hdmi.connection.IHdmiConnectionCallback",
+ "android.hardware.tv.hdmi.earc.IEArcCallback",
+ "android.hardware.usb.gadget.IUsbGadgetCallback",
+ "android.hardware.usb.IUsbCallback",
+ "android.hardware.usb.IUsbManager",
+ "android.hardware.usb.IUsbSerialReader",
+ "android.hardware.wifi.hostapd.IHostapdCallback",
+ "android.hardware.wifi.IWifiChipEventCallback",
+ "android.hardware.wifi.IWifiEventCallback",
+ "android.hardware.wifi.IWifiNanIfaceEventCallback",
+ "android.hardware.wifi.IWifiRttControllerEventCallback",
+ "android.hardware.wifi.IWifiStaIfaceEventCallback",
+ "android.hardware.wifi.supplicant.INonStandardCertCallback",
+ "android.hardware.wifi.supplicant.ISupplicantP2pIfaceCallback",
+ "android.hardware.wifi.supplicant.ISupplicantStaIfaceCallback",
+ "android.hardware.wifi.supplicant.ISupplicantStaNetworkCallback",
+ "android.health.connect.aidl.IAccessLogsResponseCallback",
+ "android.health.connect.aidl.IActivityDatesResponseCallback",
+ "android.health.connect.aidl.IAggregateRecordsResponseCallback",
+ "android.health.connect.aidl.IApplicationInfoResponseCallback",
+ "android.health.connect.aidl.IChangeLogsResponseCallback",
+ "android.health.connect.aidl.IDataStagingFinishedCallback",
+ "android.health.connect.aidl.IEmptyResponseCallback",
+ "android.health.connect.aidl.IGetChangeLogTokenCallback",
+ "android.health.connect.aidl.IGetHealthConnectDataStateCallback",
+ "android.health.connect.aidl.IGetHealthConnectMigrationUiStateCallback",
+ "android.health.connect.aidl.IGetPriorityResponseCallback",
+ "android.health.connect.aidl.IHealthConnectService",
+ "android.health.connect.aidl.IInsertRecordsResponseCallback",
+ "android.health.connect.aidl.IMedicalDataSourceResponseCallback",
+ "android.health.connect.aidl.IMedicalResourcesResponseCallback",
+ "android.health.connect.aidl.IMigrationCallback",
+ "android.health.connect.aidl.IReadMedicalResourcesResponseCallback",
+ "android.health.connect.aidl.IReadRecordsResponseCallback",
+ "android.health.connect.aidl.IRecordTypeInfoResponseCallback",
+ "android.health.connect.exportimport.IImportStatusCallback",
+ "android.health.connect.exportimport.IQueryDocumentProvidersCallback",
+ "android.health.connect.exportimport.IScheduledExportStatusCallback",
+ "android.location.ICountryDetector",
+ "android.location.IGpsGeofenceHardware",
+ "android.location.ILocationManager",
+ "android.location.provider.ILocationProviderManager",
+ "android.media.IAudioRoutesObserver",
+ "android.media.IMediaCommunicationService",
+ "android.media.IMediaCommunicationServiceCallback",
+ "android.media.IMediaController2",
+ "android.media.IMediaRoute2ProviderServiceCallback",
+ "android.media.IMediaRouterService",
+ "android.media.IMediaSession2",
+ "android.media.IMediaSession2Service",
+ "android.media.INativeSpatializerCallback",
+ "android.media.IPlaybackConfigDispatcher",
+ "android.media.IRecordingConfigDispatcher",
+ "android.media.IRemoteDisplayCallback",
+ "android.media.ISoundDoseCallback",
+ "android.media.ISpatializerHeadTrackingCallback",
+ "android.media.ITranscodingClientCallback",
+ "android.media.metrics.IMediaMetricsManager",
+ "android.media.midi.IMidiManager",
+ "android.media.musicrecognition.IMusicRecognitionAttributionTagCallback",
+ "android.media.musicrecognition.IMusicRecognitionManager",
+ "android.media.musicrecognition.IMusicRecognitionServiceCallback",
+ "android.media.projection.IMediaProjection",
+ "android.media.projection.IMediaProjectionCallback",
+ "android.media.projection.IMediaProjectionManager",
+ "android.media.projection.IMediaProjectionWatcherCallback",
+ "android.media.session.ISession",
+ "android.media.session.ISessionController",
+ "android.media.session.ISessionManager",
+ "android.media.soundtrigger.ISoundTriggerDetectionServiceClient",
+ "android.media.soundtrigger_middleware.IInjectGlobalEvent",
+ "android.media.soundtrigger_middleware.IInjectModelEvent",
+ "android.media.soundtrigger_middleware.IInjectRecognitionEvent",
+ "android.media.soundtrigger_middleware.ISoundTriggerMiddlewareService",
+ "android.media.soundtrigger_middleware.ISoundTriggerModule",
+ "android.media.tv.ad.ITvAdManager",
+ "android.media.tv.ad.ITvAdSessionCallback",
+ "android.media.tv.interactive.ITvInteractiveAppManager",
+ "android.media.tv.interactive.ITvInteractiveAppServiceCallback",
+ "android.media.tv.interactive.ITvInteractiveAppSessionCallback",
+ "android.media.tv.ITvInputHardware",
+ "android.media.tv.ITvInputManager",
+ "android.media.tv.ITvInputServiceCallback",
+ "android.media.tv.ITvInputSessionCallback",
+ "android.media.tv.ITvRemoteServiceInput",
+ "android.nearby.aidl.IOffloadCallback",
+ "android.nearby.IBroadcastListener",
+ "android.nearby.INearbyManager",
+ "android.nearby.IScanListener",
+ "android.net.connectivity.aidl.ConnectivityNative",
+ "android.net.dhcp.IDhcpEventCallbacks",
+ "android.net.dhcp.IDhcpServer",
+ "android.net.dhcp.IDhcpServerCallbacks",
+ "android.net.ICaptivePortal",
+ "android.net.IConnectivityDiagnosticsCallback",
+ "android.net.IConnectivityManager",
+ "android.net.IEthernetManager",
+ "android.net.IEthernetServiceListener",
+ "android.net.IIntResultListener",
+ "android.net.IIpConnectivityMetrics",
+ "android.net.IIpMemoryStore",
+ "android.net.IIpMemoryStoreCallbacks",
+ "android.net.IIpSecService",
+ "android.net.INetdEventCallback",
+ "android.net.INetdUnsolicitedEventListener",
+ "android.net.INetworkActivityListener",
+ "android.net.INetworkAgent",
+ "android.net.INetworkAgentRegistry",
+ "android.net.INetworkInterfaceOutcomeReceiver",
+ "android.net.INetworkManagementEventObserver",
+ "android.net.INetworkMonitor",
+ "android.net.INetworkMonitorCallbacks",
+ "android.net.INetworkOfferCallback",
+ "android.net.INetworkPolicyListener",
+ "android.net.INetworkPolicyManager",
+ "android.net.INetworkScoreService",
+ "android.net.INetworkStackConnector",
+ "android.net.INetworkStackStatusCallback",
+ "android.net.INetworkStatsService",
+ "android.net.INetworkStatsSession",
+ "android.net.IOnCompleteListener",
+ "android.net.IPacProxyManager",
+ "android.net.ip.IIpClient",
+ "android.net.ip.IIpClientCallbacks",
+ "android.net.ipmemorystore.IOnBlobRetrievedListener",
+ "android.net.ipmemorystore.IOnL2KeyResponseListener",
+ "android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener",
+ "android.net.ipmemorystore.IOnSameL3NetworkResponseListener",
+ "android.net.ipmemorystore.IOnStatusAndCountListener",
+ "android.net.ipmemorystore.IOnStatusListener",
+ "android.net.IQosCallback",
+ "android.net.ISocketKeepaliveCallback",
+ "android.net.ITestNetworkManager",
+ "android.net.ITetheredInterfaceCallback",
+ "android.net.ITetheringConnector",
+ "android.net.ITetheringEventCallback",
+ "android.net.IVpnManager",
+ "android.net.mdns.aidl.IMDnsEventListener",
+ "android.net.metrics.INetdEventListener",
+ "android.net.netstats.IUsageCallback",
+ "android.net.netstats.provider.INetworkStatsProvider",
+ "android.net.netstats.provider.INetworkStatsProviderCallback",
+ "android.net.nsd.INsdManager",
+ "android.net.nsd.INsdManagerCallback",
+ "android.net.nsd.INsdServiceConnector",
+ "android.net.nsd.IOffloadEngine",
+ "android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener",
+ "android.net.thread.IActiveOperationalDatasetReceiver",
+ "android.net.thread.IConfigurationReceiver",
+ "android.net.thread.IOperationalDatasetCallback",
+ "android.net.thread.IOperationReceiver",
+ "android.net.thread.IStateCallback",
+ "android.net.thread.IThreadNetworkController",
+ "android.net.thread.IThreadNetworkManager",
+ "android.net.vcn.IVcnManagementService",
+ "android.net.wear.ICompanionDeviceManagerProxy",
+ "android.net.wifi.aware.IWifiAwareDiscoverySessionCallback",
+ "android.net.wifi.aware.IWifiAwareEventCallback",
+ "android.net.wifi.aware.IWifiAwareMacAddressProvider",
+ "android.net.wifi.aware.IWifiAwareManager",
+ "android.net.wifi.hotspot2.IProvisioningCallback",
+ "android.net.wifi.IActionListener",
+ "android.net.wifi.IBooleanListener",
+ "android.net.wifi.IByteArrayListener",
+ "android.net.wifi.ICoexCallback",
+ "android.net.wifi.IDppCallback",
+ "android.net.wifi.IIntegerListener",
+ "android.net.wifi.IInterfaceCreationInfoCallback",
+ "android.net.wifi.ILastCallerListener",
+ "android.net.wifi.IListListener",
+ "android.net.wifi.ILocalOnlyConnectionStatusListener",
+ "android.net.wifi.ILocalOnlyHotspotCallback",
+ "android.net.wifi.IMacAddressListListener",
+ "android.net.wifi.IMapListener",
+ "android.net.wifi.INetworkRequestMatchCallback",
+ "android.net.wifi.INetworkRequestUserSelectionCallback",
+ "android.net.wifi.IOnWifiActivityEnergyInfoListener",
+ "android.net.wifi.IOnWifiDriverCountryCodeChangedListener",
+ "android.net.wifi.IOnWifiUsabilityStatsListener",
+ "android.net.wifi.IPnoScanResultsCallback",
+ "android.net.wifi.IScanDataListener",
+ "android.net.wifi.IScanResultsCallback",
+ "android.net.wifi.IScoreUpdateObserver",
+ "android.net.wifi.ISoftApCallback",
+ "android.net.wifi.IStringListener",
+ "android.net.wifi.ISubsystemRestartCallback",
+ "android.net.wifi.ISuggestionConnectionStatusListener",
+ "android.net.wifi.ISuggestionUserApprovalStatusListener",
+ "android.net.wifi.ITrafficStateCallback",
+ "android.net.wifi.ITwtCallback",
+ "android.net.wifi.ITwtCapabilitiesListener",
+ "android.net.wifi.ITwtStatsListener",
+ "android.net.wifi.IWifiBandsListener",
+ "android.net.wifi.IWifiConnectedNetworkScorer",
+ "android.net.wifi.IWifiLowLatencyLockListener",
+ "android.net.wifi.IWifiManager",
+ "android.net.wifi.IWifiNetworkSelectionConfigListener",
+ "android.net.wifi.IWifiNetworkStateChangedListener",
+ "android.net.wifi.IWifiScanner",
+ "android.net.wifi.IWifiScannerListener",
+ "android.net.wifi.IWifiVerboseLoggingStatusChangedListener",
+ "android.net.wifi.p2p.IWifiP2pListener",
+ "android.net.wifi.p2p.IWifiP2pManager",
+ "android.net.wifi.rtt.IRttCallback",
+ "android.net.wifi.rtt.IWifiRttManager",
+ "android.ondevicepersonalization.IOnDevicePersonalizationSystemService",
+ "android.ondevicepersonalization.IOnDevicePersonalizationSystemServiceCallback",
+ "android.os.IBatteryPropertiesRegistrar",
+ "android.os.ICancellationSignal",
+ "android.os.IDeviceIdentifiersPolicyService",
+ "android.os.IDeviceIdleController",
+ "android.os.IDumpstate",
+ "android.os.IDumpstateListener",
+ "android.os.IExternalVibratorService",
+ "android.os.IHardwarePropertiesManager",
+ "android.os.IHintManager",
+ "android.os.IHintSession",
+ "android.os.IIncidentCompanion",
+ "android.os.image.IDynamicSystemService",
+ "android.os.incremental.IStorageHealthListener",
+ "android.os.INetworkManagementService",
+ "android.os.IPendingIntentRef",
+ "android.os.IPowerStatsService",
+ "android.os.IProfilingResultCallback",
+ "android.os.IProfilingService",
+ "android.os.IProgressListener",
+ "android.os.IPullAtomCallback",
+ "android.os.IRecoverySystem",
+ "android.os.IRemoteCallback",
+ "android.os.ISecurityStateManager",
+ "android.os.IServiceCallback",
+ "android.os.IStatsCompanionService",
+ "android.os.IStatsManagerService",
+ "android.os.IStatsQueryCallback",
+ "android.os.ISystemConfig",
+ "android.os.ISystemUpdateManager",
+ "android.os.IThermalEventListener",
+ "android.os.IUpdateLock",
+ "android.os.IUserManager",
+ "android.os.IUserRestrictionsListener",
+ "android.os.IVibratorManagerService",
+ "android.os.IVoldListener",
+ "android.os.IVoldMountCallback",
+ "android.os.IVoldTaskListener",
+ "android.os.logcat.ILogcatManagerService",
+ "android.permission.ILegacyPermissionManager",
+ "android.permission.IPermissionChecker",
+ "android.permission.IPermissionManager",
+ "android.print.IPrintManager",
+ "android.print.IPrintSpoolerCallbacks",
+ "android.print.IPrintSpoolerClient",
+ "android.printservice.IPrintServiceClient",
+ "android.printservice.recommendation.IRecommendationServiceCallbacks",
+ "android.provider.aidl.IDeviceConfigManager",
+ "android.remoteauth.IDeviceDiscoveryListener",
+ "android.safetycenter.IOnSafetyCenterDataChangedListener",
+ "android.safetycenter.ISafetyCenterManager",
+ "android.scheduling.IRebootReadinessManager",
+ "android.scheduling.IRequestRebootReadinessStatusListener",
+ "android.security.attestationverification.IAttestationVerificationManagerService",
+ "android.security.IFileIntegrityService",
+ "android.security.keystore.IKeyAttestationApplicationIdProvider",
+ "android.security.rkp.IRegistration",
+ "android.security.rkp.IRemoteProvisioning",
+ "android.service.appprediction.IPredictionService",
+ "android.service.assist.classification.IFieldClassificationCallback",
+ "android.service.attention.IAttentionCallback",
+ "android.service.attention.IProximityUpdateCallback",
+ "android.service.autofill.augmented.IFillCallback",
+ "android.service.autofill.IConvertCredentialCallback",
+ "android.service.autofill.IFillCallback",
+ "android.service.autofill.IInlineSuggestionUiCallback",
+ "android.service.autofill.ISaveCallback",
+ "android.service.autofill.ISurfacePackageResultCallback",
+ "android.service.contentcapture.IContentCaptureServiceCallback",
+ "android.service.contentcapture.IContentProtectionAllowlistCallback",
+ "android.service.contentcapture.IDataShareCallback",
+ "android.service.credentials.IBeginCreateCredentialCallback",
+ "android.service.credentials.IBeginGetCredentialCallback",
+ "android.service.credentials.IClearCredentialStateCallback",
+ "android.service.dreams.IDreamManager",
+ "android.service.games.IGameServiceController",
+ "android.service.games.IGameSessionController",
+ "android.service.notification.IStatusBarNotificationHolder",
+ "android.service.oemlock.IOemLockService",
+ "android.service.ondeviceintelligence.IProcessingUpdateStatusCallback",
+ "android.service.ondeviceintelligence.IRemoteProcessingService",
+ "android.service.ondeviceintelligence.IRemoteStorageService",
+ "android.service.persistentdata.IPersistentDataBlockService",
+ "android.service.resolver.IResolverRankerResult",
+ "android.service.rotationresolver.IRotationResolverCallback",
+ "android.service.textclassifier.ITextClassifierCallback",
+ "android.service.textclassifier.ITextClassifierService",
+ "android.service.timezone.ITimeZoneProviderManager",
+ "android.service.trust.ITrustAgentServiceCallback",
+ "android.service.voice.IDetectorSessionStorageService",
+ "android.service.voice.IDetectorSessionVisualQueryDetectionCallback",
+ "android.service.voice.IDspHotwordDetectionCallback",
+ "android.service.wallpaper.IWallpaperConnection",
+ "android.speech.IRecognitionListener",
+ "android.speech.IRecognitionService",
+ "android.speech.IRecognitionServiceManager",
+ "android.speech.tts.ITextToSpeechManager",
+ "android.speech.tts.ITextToSpeechSession",
+ "android.system.composd.ICompilationTaskCallback",
+ "android.system.virtualizationmaintenance.IVirtualizationReconciliationCallback",
+ "android.system.virtualizationservice.IVirtualMachineCallback",
+ "android.system.vmtethering.IVmTethering",
+ "android.telephony.imsmedia.IImsAudioSession",
+ "android.telephony.imsmedia.IImsAudioSessionCallback",
+ "android.telephony.imsmedia.IImsMedia",
+ "android.telephony.imsmedia.IImsMediaCallback",
+ "android.telephony.imsmedia.IImsTextSession",
+ "android.telephony.imsmedia.IImsTextSessionCallback",
+ "android.telephony.imsmedia.IImsVideoSession",
+ "android.telephony.imsmedia.IImsVideoSessionCallback",
+ "android.tracing.ITracingServiceProxy",
+ "android.uwb.IOnUwbActivityEnergyInfoListener",
+ "android.uwb.IUwbAdapter",
+ "android.uwb.IUwbAdapterStateCallbacks",
+ "android.uwb.IUwbAdfProvisionStateCallbacks",
+ "android.uwb.IUwbOemExtensionCallback",
+ "android.uwb.IUwbRangingCallbacks",
+ "android.uwb.IUwbVendorUciCallback",
+ "android.view.accessibility.IAccessibilityInteractionConnectionCallback",
+ "android.view.accessibility.IAccessibilityManager",
+ "android.view.accessibility.IMagnificationConnectionCallback",
+ "android.view.accessibility.IRemoteMagnificationAnimationCallback",
+ "android.view.autofill.IAutoFillManager",
+ "android.view.autofill.IAutofillWindowPresenter",
+ "android.view.contentcapture.IContentCaptureManager",
+ "android.view.IDisplayChangeWindowCallback",
+ "android.view.IDisplayWindowListener",
+ "android.view.IInputFilter",
+ "android.view.IInputFilterHost",
+ "android.view.IInputMonitorHost",
+ "android.view.IRecentsAnimationController",
+ "android.view.IRemoteAnimationFinishedCallback",
+ "android.view.ISensitiveContentProtectionManager",
+ "android.view.IWindowId",
+ "android.view.IWindowManager",
+ "android.view.IWindowSession",
+ "android.view.translation.ITranslationManager",
+ "android.view.translation.ITranslationServiceCallback",
+ "android.webkit.IWebViewUpdateService",
+ "android.window.IBackAnimationFinishedCallback",
+ "android.window.IDisplayAreaOrganizerController",
+ "android.window.ITaskFragmentOrganizerController",
+ "android.window.ITaskOrganizerController",
+ "android.window.ITransitionMetricsReporter",
+ "android.window.IUnhandledDragCallback",
+ "android.window.IWindowContainerToken",
+ "android.window.IWindowlessStartingSurfaceCallback",
+ "android.window.IWindowOrganizerController",
+ "androidx.core.uwb.backend.IUwb",
+ "androidx.core.uwb.backend.IUwbClient",
+ "com.android.clockwork.modes.IModeManager",
+ "com.android.clockwork.modes.IStateChangeListener",
+ "com.android.clockwork.power.IWearPowerService",
+ "com.android.devicelockcontroller.IDeviceLockControllerService",
+ "com.android.devicelockcontroller.storage.IGlobalParametersService",
+ "com.android.devicelockcontroller.storage.ISetupParametersService",
+ "com.android.federatedcompute.services.training.aidl.IIsolatedTrainingService",
+ "com.android.federatedcompute.services.training.aidl.ITrainingResultCallback",
+ "com.android.internal.app.IAppOpsActiveCallback",
+ "com.android.internal.app.ILogAccessDialogCallback",
+ "com.android.internal.app.ISoundTriggerService",
+ "com.android.internal.app.ISoundTriggerSession",
+ "com.android.internal.app.IVoiceInteractionAccessibilitySettingsListener",
+ "com.android.internal.app.IVoiceInteractionManagerService",
+ "com.android.internal.app.IVoiceInteractionSessionListener",
+ "com.android.internal.app.IVoiceInteractionSessionShowCallback",
+ "com.android.internal.app.IVoiceInteractionSoundTriggerSession",
+ "com.android.internal.app.procstats.IProcessStats",
+ "com.android.internal.appwidget.IAppWidgetService",
+ "com.android.internal.backup.ITransportStatusCallback",
+ "com.android.internal.compat.IOverrideValidator",
+ "com.android.internal.compat.IPlatformCompat",
+ "com.android.internal.compat.IPlatformCompatNative",
+ "com.android.internal.graphics.fonts.IFontManager",
+ "com.android.internal.inputmethod.IAccessibilityInputMethodSessionCallback",
+ "com.android.internal.inputmethod.IConnectionlessHandwritingCallback",
+ "com.android.internal.inputmethod.IImeTracker",
+ "com.android.internal.inputmethod.IInlineSuggestionsRequestCallback",
+ "com.android.internal.inputmethod.IInputContentUriToken",
+ "com.android.internal.inputmethod.IInputMethodPrivilegedOperations",
+ "com.android.internal.inputmethod.IInputMethodSessionCallback",
+ "com.android.internal.net.INetworkWatchlistManager",
+ "com.android.internal.os.IBinaryTransparencyService",
+ "com.android.internal.os.IDropBoxManagerService",
+ "com.android.internal.policy.IKeyguardDismissCallback",
+ "com.android.internal.policy.IKeyguardDrawnCallback",
+ "com.android.internal.policy.IKeyguardExitCallback",
+ "com.android.internal.policy.IKeyguardStateCallback",
+ "com.android.internal.statusbar.IAddTileResultCallback",
+ "com.android.internal.statusbar.ISessionListener",
+ "com.android.internal.statusbar.IStatusBarService",
+ "com.android.internal.telecom.IDeviceIdleControllerAdapter",
+ "com.android.internal.telecom.IInternalServiceRetriever",
+ "com.android.internal.telephony.IMms",
+ "com.android.internal.telephony.ITelephonyRegistry",
+ "com.android.internal.textservice.ISpellCheckerServiceCallback",
+ "com.android.internal.textservice.ITextServicesManager",
+ "com.android.internal.view.IDragAndDropPermissions",
+ "com.android.internal.view.IInputMethodManager",
+ "com.android.internal.view.inline.IInlineContentProvider",
+ "com.android.internal.widget.ILockSettings",
+ "com.android.net.IProxyPortListener",
+ "com.android.net.module.util.IRoutingCoordinator",
+ "com.android.ondevicepersonalization.libraries.plugin.internal.IPluginCallback",
+ "com.android.ondevicepersonalization.libraries.plugin.internal.IPluginExecutorService",
+ "com.android.ondevicepersonalization.libraries.plugin.internal.IPluginStateCallback",
+ "com.android.rkpdapp.IGetKeyCallback",
+ "com.android.rkpdapp.IGetRegistrationCallback",
+ "com.android.rkpdapp.IRegistration",
+ "com.android.rkpdapp.IRemoteProvisioning",
+ "com.android.rkpdapp.IStoreUpgradedKeyCallback",
+ "com.android.sdksandbox.IComputeSdkStorageCallback",
+ "com.android.sdksandbox.ILoadSdkInSandboxCallback",
+ "com.android.sdksandbox.IRequestSurfacePackageFromSdkCallback",
+ "com.android.sdksandbox.ISdkSandboxManagerToSdkSandboxCallback",
+ "com.android.sdksandbox.ISdkSandboxService",
+ "com.android.sdksandbox.IUnloadSdkInSandboxCallback",
+ "com.android.server.profcollect.IProviderStatusCallback",
+ "com.android.server.thread.openthread.IChannelMasksReceiver",
+ "com.android.server.thread.openthread.INsdPublisher",
+ "com.android.server.thread.openthread.IOtDaemonCallback",
+ "com.android.server.thread.openthread.IOtStatusReceiver",
+ "com.google.android.clockwork.ambient.offload.IDisplayOffloadService",
+ "com.google.android.clockwork.ambient.offload.IDisplayOffloadTransitionFinishedCallbacks",
+ "com.google.android.clockwork.healthservices.IHealthService",
+ "vendor.google_clockwork.healthservices.IHealthServicesCallback",
+)
diff --git a/tools/lint/utils/README.md b/tools/lint/utils/README.md
new file mode 100644
index 0000000..b5583c5
--- /dev/null
+++ b/tools/lint/utils/README.md
@@ -0,0 +1,11 @@
+# Utility Android Lint Checks for AOSP
+
+This directory contains scripts that execute utility Android Lint Checks for AOSP, specifically:
+* `enforce_permission_counter.py`: Provides statistics regarding the percentage of annotated/not
+ annotated `AIDL` methods with `@EnforcePermission` annotations.
+* `generate-exempt-aidl-interfaces.sh`: Provides a list of all `AIDL` interfaces in the entire
+ source tree.
+
+When adding a new utility Android Lint check to this directory, consider adding any utility or
+data processing tool you might require. Make sure that your contribution is documented in this
+README file.
diff --git a/tools/lint/utils/checks/src/main/java/com/google/android/lint/AndroidUtilsIssueRegistry.kt b/tools/lint/utils/checks/src/main/java/com/google/android/lint/AndroidUtilsIssueRegistry.kt
index fa61c42..9842881 100644
--- a/tools/lint/utils/checks/src/main/java/com/google/android/lint/AndroidUtilsIssueRegistry.kt
+++ b/tools/lint/utils/checks/src/main/java/com/google/android/lint/AndroidUtilsIssueRegistry.kt
@@ -19,6 +19,7 @@
import com.android.tools.lint.client.api.IssueRegistry
import com.android.tools.lint.client.api.Vendor
import com.android.tools.lint.detector.api.CURRENT_API
+import com.google.android.lint.aidl.ExemptAidlInterfacesGenerator
import com.google.android.lint.aidl.AnnotatedAidlCounter
import com.google.auto.service.AutoService
@@ -27,6 +28,7 @@
class AndroidUtilsIssueRegistry : IssueRegistry() {
override val issues = listOf(
AnnotatedAidlCounter.ISSUE_ANNOTATED_AIDL_COUNTER,
+ ExemptAidlInterfacesGenerator.ISSUE_PERMISSION_ANNOTATION_EXEMPT_AIDL_INTERFACES,
)
override val api: Int
@@ -38,6 +40,6 @@
override val vendor: Vendor = Vendor(
vendorName = "Android",
feedbackUrl = "http://b/issues/new?component=315013",
- contact = "tweek@google.com"
+ contact = "android-platform-abuse-prevention-withfriends@google.com"
)
}
diff --git a/tools/lint/utils/checks/src/main/java/com/google/android/lint/aidl/ExemptAidlInterfacesGenerator.kt b/tools/lint/utils/checks/src/main/java/com/google/android/lint/aidl/ExemptAidlInterfacesGenerator.kt
new file mode 100644
index 0000000..6ad223c
--- /dev/null
+++ b/tools/lint/utils/checks/src/main/java/com/google/android/lint/aidl/ExemptAidlInterfacesGenerator.kt
@@ -0,0 +1,96 @@
+/*
+ * 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.google.android.lint.aidl
+
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Context
+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 org.jetbrains.uast.UBlockExpression
+import org.jetbrains.uast.UMethod
+
+/**
+ * Generates a set of fully qualified AIDL Interface names present in the entire source tree with
+ * the following requirement: their implementations have to be inside directories whose path
+ * prefixes match `systemServicePathPrefixes`.
+ */
+class ExemptAidlInterfacesGenerator : AidlImplementationDetector() {
+ private val targetExemptAidlInterfaceNames = mutableSetOf<String>()
+ private val systemServicePathPrefixes = setOf(
+ "frameworks/base/services",
+ "frameworks/base/apex",
+ "frameworks/opt/wear",
+ "packages/modules"
+ )
+
+ // We could've improved performance by visiting classes rather than methods, however, this lint
+ // check won't be run regularly, hence we've decided not to add extra overrides to
+ // AidlImplementationDetector.
+ override fun visitAidlMethod(
+ context: JavaContext,
+ node: UMethod,
+ interfaceName: String,
+ body: UBlockExpression
+ ) {
+ val filePath = context.file.path
+
+ // We perform `filePath.contains` instead of `filePath.startsWith` since getting the
+ // relative path of a source file is non-trivial. That is because `context.file.path`
+ // returns the path to where soong builds the file (i.e. /out/soong/...). Moreover, the
+ // logic to extract the relative path would need to consider several /out/soong/...
+ // locations patterns.
+ if (systemServicePathPrefixes.none { filePath.contains(it) }) return
+
+ val fullyQualifiedInterfaceName =
+ getContainingAidlInterfaceQualified(context, node) ?: return
+
+ targetExemptAidlInterfaceNames.add("\"$fullyQualifiedInterfaceName\",")
+ }
+
+ override fun afterCheckEachProject(context: Context) {
+ if (targetExemptAidlInterfaceNames.isEmpty()) return
+
+ val message = targetExemptAidlInterfaceNames.joinToString("\n")
+
+ context.report(
+ ISSUE_PERMISSION_ANNOTATION_EXEMPT_AIDL_INTERFACES,
+ context.getLocation(context.project.dir),
+ "\n" + message + "\n",
+ )
+ }
+
+ companion object {
+ @JvmField
+ val ISSUE_PERMISSION_ANNOTATION_EXEMPT_AIDL_INTERFACES = Issue.create(
+ id = "PermissionAnnotationExemptAidlInterfaces",
+ briefDescription = "Returns a set of all AIDL interfaces",
+ explanation = """
+ Produces the exemptAidlInterfaces set used by PermissionAnnotationDetector
+ """.trimIndent(),
+ category = Category.SECURITY,
+ priority = 5,
+ severity = Severity.INFORMATIONAL,
+ implementation = Implementation(
+ ExemptAidlInterfacesGenerator::class.java,
+ Scope.JAVA_FILE_SCOPE
+ )
+ )
+ }
+}
diff --git a/tools/lint/utils/checks/src/test/java/com/google/android/lint/aidl/ExemptAidlInterfacesGeneratorTest.kt b/tools/lint/utils/checks/src/test/java/com/google/android/lint/aidl/ExemptAidlInterfacesGeneratorTest.kt
new file mode 100644
index 0000000..9a17bb4
--- /dev/null
+++ b/tools/lint/utils/checks/src/test/java/com/google/android/lint/aidl/ExemptAidlInterfacesGeneratorTest.kt
@@ -0,0 +1,191 @@
+/*
+ * 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.google.android.lint.aidl
+
+import com.android.tools.lint.checks.infrastructure.LintDetectorTest
+import com.android.tools.lint.checks.infrastructure.TestFile
+import com.android.tools.lint.checks.infrastructure.TestLintTask
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+
+class ExemptAidlInterfacesGeneratorTest : LintDetectorTest() {
+ override fun getDetector(): Detector = ExemptAidlInterfacesGenerator()
+
+ override fun getIssues(): List<Issue> = listOf(
+ ExemptAidlInterfacesGenerator.ISSUE_PERMISSION_ANNOTATION_EXEMPT_AIDL_INTERFACES,
+ )
+
+ override fun lint(): TestLintTask = super.lint().allowMissingSdk(true)
+
+ fun testMultipleAidlInterfacesImplemented() {
+ lint()
+ .files(
+ java(
+ createVisitedPath("TestClass1.java"),
+ """
+ package com.android.server;
+ public class TestClass1 extends IFoo.Stub {
+ public void testMethod() {}
+ }
+ """
+ )
+ .indented(),
+ java(
+ createVisitedPath("TestClass2.java"),
+ """
+ package com.android.server;
+ public class TestClass2 extends IBar.Stub {
+ public void testMethod() {}
+ }
+ """
+ )
+ .indented(),
+ *stubs,
+ )
+ .run()
+ .expect(
+ """
+ app: Information: "IFoo",
+ "IBar", [PermissionAnnotationExemptAidlInterfaces]
+ 0 errors, 0 warnings
+ """
+ )
+ }
+
+ fun testSingleAidlInterfaceRepeated() {
+ lint()
+ .files(
+ java(
+ createVisitedPath("TestClass1.java"),
+ """
+ package com.android.server;
+ public class TestClass1 extends IFoo.Stub {
+ public void testMethod() {}
+ }
+ """
+ )
+ .indented(),
+ java(
+ createVisitedPath("TestClass2.java"),
+ """
+ package com.android.server;
+ public class TestClass2 extends IFoo.Stub {
+ public void testMethod() {}
+ }
+ """
+ )
+ .indented(),
+ *stubs,
+ )
+ .run()
+ .expect(
+ """
+ app: Information: "IFoo", [PermissionAnnotationExemptAidlInterfaces]
+ 0 errors, 0 warnings
+ """
+ )
+ }
+
+ fun testAnonymousClassExtendsAidlStub() {
+ lint()
+ .files(
+ java(
+ createVisitedPath("TestClass.java"),
+ """
+ package com.android.server;
+ public class TestClass {
+ private IBinder aidlImpl = new IFoo.Stub() {
+ public void testMethod() {}
+ };
+ }
+ """
+ )
+ .indented(),
+ *stubs,
+ )
+ .run()
+ .expect(
+ """
+ app: Information: "IFoo", [PermissionAnnotationExemptAidlInterfaces]
+ 0 errors, 0 warnings
+ """
+ )
+ }
+
+ fun testNoAidlInterfacesImplemented() {
+ lint()
+ .files(
+ java(
+ createVisitedPath("TestClass.java"),
+ """
+ package com.android.server;
+ public class TestClass {
+ public void testMethod() {}
+ }
+ """
+ )
+ .indented(),
+ *stubs
+ )
+ .run()
+ .expectClean()
+ }
+
+ fun testAidlInterfaceImplementedInIgnoredDirectory() {
+ lint()
+ .files(
+ java(
+ ignoredPath,
+ """
+ package com.android.server;
+ public class TestClass1 extends IFoo.Stub {
+ public void testMethod() {}
+ }
+ """
+ )
+ .indented(),
+ *stubs,
+ )
+ .run()
+ .expectClean()
+ }
+
+ private val interfaceIFoo: TestFile = java(
+ """
+ public interface IFoo extends android.os.IInterface {
+ public static abstract class Stub extends android.os.Binder implements IFoo {}
+ public void testMethod();
+ }
+ """
+ ).indented()
+
+ private val interfaceIBar: TestFile = java(
+ """
+ public interface IBar extends android.os.IInterface {
+ public static abstract class Stub extends android.os.Binder implements IBar {}
+ public void testMethod();
+ }
+ """
+ ).indented()
+
+ private val stubs = arrayOf(interfaceIFoo, interfaceIBar)
+
+ private fun createVisitedPath(filename: String) =
+ "src/frameworks/base/services/java/com/android/server/$filename"
+
+ private val ignoredPath = "src/test/pkg/TestClass.java"
+}
diff --git a/tools/lint/utils/generate-exempt-aidl-interfaces.sh b/tools/lint/utils/generate-exempt-aidl-interfaces.sh
new file mode 100755
index 0000000..44dcdd7
--- /dev/null
+++ b/tools/lint/utils/generate-exempt-aidl-interfaces.sh
@@ -0,0 +1,59 @@
+#
+# 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.
+#
+
+# Create a directory for the results and a nested temporary directory.
+mkdir -p $ANDROID_BUILD_TOP/out/soong/exempt_aidl_interfaces_generator_output/tmp
+
+# Create a copy of `AndroidGlobalLintChecker.jar` to restore it afterwards.
+cp $ANDROID_BUILD_TOP/prebuilts/cmdline-tools/AndroidGlobalLintChecker.jar \
+ $ANDROID_BUILD_TOP/out/soong/exempt_aidl_interfaces_generator_output/AndroidGlobalLintChecker.jar
+
+# Configure the environment variable required for running the lint check on the entire source tree.
+export ANDROID_LINT_CHECK=PermissionAnnotationExemptAidlInterfaces
+
+# Build the target corresponding to the lint checks present in the `utils` directory.
+m AndroidUtilsLintChecker
+
+# Replace `AndroidGlobalLintChecker.jar` with the newly built `jar` file.
+cp $ANDROID_BUILD_TOP/out/host/linux-x86/framework/AndroidUtilsLintChecker.jar \
+ $ANDROID_BUILD_TOP/prebuilts/cmdline-tools/AndroidGlobalLintChecker.jar;
+
+# Run the lint check on the entire source tree.
+m lint-check
+
+# Copy the archive containing the results of `lint-check` into the temporary directory.
+cp $ANDROID_BUILD_TOP/out/soong/lint-report-text.zip \
+ $ANDROID_BUILD_TOP/out/soong/exempt_aidl_interfaces_generator_output/tmp
+
+cd $ANDROID_BUILD_TOP/out/soong/exempt_aidl_interfaces_generator_output/tmp
+
+# Unzip the archive containing the results of `lint-check`.
+unzip lint-report-text.zip
+
+# Concatenate the results of `lint-check` into a single string.
+concatenated_reports=$(find . -type f | xargs cat)
+
+# Extract the fully qualified names of the AIDL Interfaces from the concatenated results. Output
+# this list into `out/soong/exempt_aidl_interfaces_generator_output/exempt_aidl_interfaces`.
+echo $concatenated_reports | grep -Eo '\"([a-zA-Z0-9_]*\.)+[a-zA-Z0-9_]*\",' | sort | uniq > ../exempt_aidl_interfaces
+
+# Remove the temporary directory.
+rm -rf $ANDROID_BUILD_TOP/out/soong/exempt_aidl_interfaces_generator_output/tmp
+
+# Restore the original copy of `AndroidGlobalLintChecker.jar` and delete the copy.
+cp $ANDROID_BUILD_TOP/out/soong/exempt_aidl_interfaces_generator_output/AndroidGlobalLintChecker.jar \
+ $ANDROID_BUILD_TOP/prebuilts/cmdline-tools/AndroidGlobalLintChecker.jar
+rm $ANDROID_BUILD_TOP/out/soong/exempt_aidl_interfaces_generator_output/AndroidGlobalLintChecker.jar
diff --git a/tools/protologtool/src/com/android/protolog/tool/ViewerConfigProtoBuilder.kt b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigProtoBuilder.kt
index 0115339..245e802 100644
--- a/tools/protologtool/src/com/android/protolog/tool/ViewerConfigProtoBuilder.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigProtoBuilder.kt
@@ -53,7 +53,7 @@
.setMessageId(key)
.setMessage(log.messageString)
.setLevel(
- ProtoLogLevel.forNumber(log.logLevel.ordinal + 1))
+ ProtoLogLevel.forNumber(log.logLevel.id))
.setGroupId(groupId)
.setLocation(log.position)
)